使用 RxJava2 和 Mosby 避免 NPE

Avoidng NPE using RxJava2 with Mosby

我使用 RxJava 以及 Retrofit 和 Mosby/Conductor 创建了一个应用程序。现在我有一个关于视图处理及其结果的问题。

考虑以下代码。

public class IndexPresenter extends MvpBasePresenter<IIndexView> {
    @Inject
    VideoService videoService;

    private CompositeDisposable compositeDisposable = new CompositeDisposable();

    private String lastVideoId;

    public IndexPresenter(Context context) {
        // Dagger Inject
    }

    @Override
    public void detachView(boolean retainInstance) {
        compositeDisposable.clear();
        super.detachView(retainInstance);
    }

    public void getTimeline() {
        Disposable disposable = videoService
                .getTimeline(null)
                .delay(5, TimeUnit.SECONDS)
                .compose(Util.schedulers())
                .doOnSubscribe(__ -> getView().startLoading())
                .doFinally(() -> getView().stopLoading())
                .doOnError(throwable -> Timber.d(throwable, "failed getting timeline data"))
                .subscribe(timelineResponse -> {
                    getView().onIndexDataLoaded(timelineResponse.getMeta().getArtists(), timelineResponse.getVideos());
                    int size = timelineResponse.getVideos().size();
                    lastVideoId = timelineResponse.getVideos().get(size - 1).getId();
                }, throwable -> getView().onIndexDataFailed());
        compositeDisposable.add(disposable);
    }

    public void loadMore() {
        if (lastVideoId != null && lastVideoId.equals("-1")) {
            return;
        }
        Disposable disposable = videoService
                .getTimeline(lastVideoId)
                .compose(Util.schedulers())
                .doOnSubscribe(__ -> getView().startLoading())
                .doFinally(() -> getView().stopLoading())
                .doOnError(throwable -> Timber.d(throwable, "failed loading more items"))
                .subscribe(timelineResponse -> {
                    getView().onNextPageLoaded(timelineResponse.getVideos());
                    int size = timelineResponse.getVideos().size();
                    if (size == 0) {
                        lastVideoId = "-1";
                    } else {
                        lastVideoId = timelineResponse.getVideos().get(size - 1).getId();
                    }
                }, throwable -> getView().onIndexDataFailed());
        compositeDisposable.add(disposable);
    }
}

我想知道的是,每次访问getView()时是否还要进行无效检查?在分离之前处理所有的一次性用品不处理这个问题吗?

如果 您在 detachView() 中取消订阅/处理您的一次性物品,就像您所做的那样

AND

IF RxJava 订阅回调 onNext() 运行 在 android 主线程上(我假设 Util.schedulers() 设置 .observeOn(AndroidSchedulers.mainThread()))

然后(并且只有那时)

保证你永远不会运行进入getView()returnsnull.

的场景

因为: detachView() 被 Mosby 在 android 的主线程上调用。如果 onNext 回调也在 android 的主线程上 运行s 那么显然 运行 在同一个线程上并且它们永远不能同时 运行时间而是一个接一个。因此,执行顺序为:

  1. onNext() 回调 --> 视图仍然附加,所以 view != null
  2. detachView() --> 取消订阅,所以 onNext() 永远不会被再次调用,你永远不会 运行 在 view == null
  3. 的情况下

  1. detachView() --> 取消订阅,因此 onNext() 不再被调用
  2. 永远不会发生,因为订阅已被处理,所以在 view == null
  3. 的情况下永远不会 运行

在你的具体情况下:我猜你在 android 的主线程 (Util.schedulers()) 上观察并且你也正确地处理了可观察的,所以你永远不会 运行 在 getView() == null