使用 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 那么显然 运行 在同一个线程上并且它们永远不能同时 运行时间而是一个接一个。因此,执行顺序为:
- onNext() 回调 --> 视图仍然附加,所以
view != null
- detachView() --> 取消订阅,所以
onNext()
永远不会被再次调用,你永远不会 运行 在 view == null
的情况下
或
- detachView() --> 取消订阅,因此
onNext()
不再被调用
- 永远不会发生,因为订阅已被处理,所以在
view == null
的情况下永远不会 运行
在你的具体情况下:我猜你在 android 的主线程 (Util.schedulers()
) 上观察并且你也正确地处理了可观察的,所以你永远不会 运行 在 getView() == null
我使用 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 那么显然 运行 在同一个线程上并且它们永远不能同时 运行时间而是一个接一个。因此,执行顺序为:
- onNext() 回调 --> 视图仍然附加,所以
view != null
- detachView() --> 取消订阅,所以
onNext()
永远不会被再次调用,你永远不会 运行 在view == null
的情况下
或
- detachView() --> 取消订阅,因此
onNext()
不再被调用 - 永远不会发生,因为订阅已被处理,所以在
view == null
的情况下永远不会 运行
在你的具体情况下:我猜你在 android 的主线程 (Util.schedulers()
) 上观察并且你也正确地处理了可观察的,所以你永远不会 运行 在 getView() == null