互联网检查,使用MVP、RX和改装时应放置在何处



我已经阅读了这篇文章。所以我真的同意第二个帖子,演讲者不应该知道安卓系统的具体情况。所以我想的是把互联网检查放在服务层。我使用Rx Java进行网络呼叫,所以我可以在进行服务呼叫之前进行网络检查,所以这种方式我需要手动抛出和IOException,因为当网络不可用时,我需要在视图中显示错误页面,另一种选择是我为没有互联网创建自己的错误类

Observable<PaginationResponse<Notification>> response = Observable.create(new Observable.OnSubscribe<PaginationResponse<Notification>>() {
            @Override
            public void call(Subscriber<? super PaginationResponse<Notification>> subscriber) {
                if (isNetworkConnected()) {
                    Call<List<Notification>> call = mService.getNotifications();
                    try {
                        Response<List<Notification>> response = call.execute();
                        processPaginationResponse(subscriber, response);
                    } catch (IOException e) {
                        e.printStackTrace();
                        subscriber.onError(e);
                    }
                } else {
//This is I am adding manually
                    subscriber.onError(new IOException);
                }
                subscriber.onCompleted();
            }
        });

我认为的另一种方法是向OkHttpClient添加拦截器,并将其设置为改造

OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                if (!isNetworkConnected()) {
                    throw new IOException();
                }
                final Request.Builder builder = chain.request().newBuilder();
                Request request = builder.build();
                return chain.proceed(request);
            }
        });

现在第二种方法更具可扩展性,但我不确定它是否有效,因为我不必要地调用服务方法和调用.execute((方法。

有什么建议应该用哪种方式吗?我判断方式的参数也是

  • 效率

  • 可扩展性

  • Generic:我希望这个相同的逻辑可以在遵循类似架构的应用程序中使用,其中MVP和Repository/Datarovider(可以从网络/db提供数据(

如果您已经在使用任何其他方式,也欢迎其他建议

首先,我们创建一个用于检查互联网连接的实用程序,有两种方法可以创建该实用程序,一种是该实用程序只发出一次状态,看起来像这样,

public class InternetConnection {
    public static Observable<Boolean> isInternetOn(Context context) {
        ConnectivityManager connectivityManager
                = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return Observable.just(activeNetworkInfo != null && activeNetworkInfo.isConnected());
    }
}

创建该实用程序的另一种方法是,如果它发生变化,该实用程序将继续发出连接状态,看起来像这样,

public class InternetConnection {
    public Observable<Boolean> isInternetOn(Context context) {
        final IntentFilter filter = new IntentFilter();
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        return Observable.create(new Observable.OnSubscribe<Boolean>() {
            @Override
            public void call(final Subscriber<? super Boolean> subscriber) {
                final BroadcastReceiver receiver = new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                        NetworkInfo netInfo = cm.getActiveNetworkInfo();
                        subscriber.onNext(netInfo != null && netInfo.isConnected());
                    }
                };
                context.registerReceiver(receiver, filter);
                subscriber.add(unsubscribeInUiThread(() -> context.unregisterReceiver(receiver)));
            }
        }).defaultIfEmpty(false);
    }
    private Subscription unsubscribeInUiThread(final Action0 unsubscribe) {
        return Subscriptions.create(() -> {
            if (Looper.getMainLooper() == Looper.myLooper()) {
                unsubscribe.call();
            } else {
                final Scheduler.Worker inner = AndroidSchedulers.mainThread().createWorker();
                inner.schedule(() -> {
                    unsubscribe.call();
                    inner.unsubscribe();
                });
            }
        });
    }
}

接下来,在您的dataSource或Presenter中,在执行任何网络操作之前,请使用switchMap或flatMap检查互联网连接,如下所示,

private Observable<List<GitHubUser>> getGitHubUsersFromRetrofit() {
    return isInternetOn(context)
            .filter(connectionStatus -> connectionStatus)
            .switchMap(connectionStatus -> gitHubApiInterface.getGitHubUsersList()
                    .map(gitHubUserList -> {
                       gitHubUserDao.storeOrUpdateGitHubUserList(gitHubUserList);
                        return gitHubUserList;
                    }));
}

请注意,我们使用的是switchMap而不是flatMap。为什么要切换Map?因为,我们这里有两个数据流,第一个是互联网连接,第二个是改装。首先,我们将获取连接状态值(true/false(,如果我们有活动连接,我们将创建一个新的改装流并返回开始获取结果,如果我们的连接状态发生变化,switchMap将首先停止现有的改装连接,然后决定我们是需要启动一个新连接还是忽略它。

编辑:这是其中一个样本,可能会提供更好的清晰度https://github.com/viraj49/Realm_android-injection-rx-test/blob/master/app-safeIntegration/src/main/java/tank/viraj/realm/dataSource/GitHubUserListDataSource.java

第2版:

你们的意思是,一旦互联网恢复,switch地图会自己尝试吗?

是和否,让我们先来看看flatMap&switchMap。假设我们有一个editText,我们根据用户类型从网络中搜索一些信息,每次用户添加新字符时,我们都必须进行新的查询(可以通过debounce来减少(,现在有这么多网络呼叫,只有最新的结果是有用的,使用flatMap,我们将收到我们对网络进行的所有呼叫的所有结果,另一方面,使用switchMap,在进行查询的那一刻,所有以前的调用都将被丢弃。

现在这里的解决方案由两部分组成,

  1. 我们需要一个不断发出当前网络状态的Observable,上面的第一个InternetConnection发送状态一次并调用onComplete((,但第二个有一个广播接收器,当网络状态发生变化时,它将继续发送onNext((。如果你需要一个反应性的解决方案去案例2

  2. 假设您选择InternetConnection案例2,在这种情况下使用switchMap((,因为当网络状态发生变化时,我们需要停止正在进行的改装,然后根据网络状态进行新的呼叫或不进行呼叫。

我如何让我的观点知道错误是互联网上的,这也是可扩展的,因为我需要处理每一个网络呼叫,关于编写包装器的任何建议?

编写包装器是一个很好的选择,您可以创建自己的自定义响应,该响应可以从一组可能的响应中获取多个条目,例如SUCCESS_INTERNET、SUCCESS_LOGIN、ERROR_INVALID_ID

第3版:请在此处查找更新的InternetConnectionUtilhttps://github.com/viraj49/Realm_android-injection-rx-test/blob/master/app-safeIntegration/src/main/java/tank/viraj/realm/util/InternetConnection.java

关于同一主题的更多详细信息,请点击此处:https://medium.com/@Viraj.Tank/android-mvp-that-survives-view-life-cycle-configuration-internet-changes-part-2-6b1e2b5c55294

第四版:我最近使用安卓架构组件LiveData创建了一个互联网实用程序,你可以在这里找到完整的源代码,https://github.com/viraj49/Internet-Utitliy-using-AAC-LiveData

代码的详细描述在这里,https://medium.com/@Viraj.Tank/internet-utility-using-android-architecture-components-livedata-e828a0fcd3db

相关内容

  • 没有找到相关文章

最新更新