我正在使用新的莫斯比MVI库作为一个新的演示应用程序。当在演示程序中定义意图时,当视图被附加时触发/发出意图时,它是不一致的。
例如:让我们在活动中定义非常简单的意图
public Observable<Boolean> intentLoadData(){
return Observable.just(true);
}推荐人将意图绑定如下:
@Override
protected void bindIntents() {
Observable<MailListViewState> loadData = intent(ExampleViewContract::intentLoadData).flatMap(interactor::loadData)
.observeOn(AndroidSchedulers.mainThread());
subscribeViewState(loadData, ExampleViewContract::render);
}这个意图很好。当导航到不同的活动(详细信息视图)并返回导航时,bindIntents()被称为意图被重新创建。intentLoadData()不发出新项,MviBasePresenter将使用内部BehaviorSubject提供以前的ViewState。
我的问题是:当我稍微调整意图(用于重新加载数据)时,。当视图重新附加时,该意图开始发出一个项。
因此,让我们改变意图,以便:
private PublishSubject<Boolean> mReloadDataSubject = PublishSubject.create();
private void reloadData(){
mReloadDataSubject.onNext(true);
}
public Observable<Boolean> intentLoadData(){
return mReloadDataSubject.startWith(true);
}当导航到一个新的活动并返回时,否。当重新附加视图时,意图将发出一个新项。在我的例子中,这会导致一个新的APU调用到后端来重新加载数据,而不是重用最后一个ViewState。即使从未调用reloadData(),也会发生这种情况。
这种行为感觉非常不一致。当在重新附加视图期间触发意图时,我如何感觉更受控制?
更新:对于我来说,更有趣的是,如何避免在重新附加时自动发出意图,而不完成可观察到的操作。随着PublishSubject的引入,即使只是旋转,活动也会重新加载整个数据。
发布于 2017-02-22 09:53:06
为了回答我自己的问题并总结意见,这是我的解决方案:
首先,我们必须了解Mosby3 MVI是如何还原视图的,例如:旋转之后,来回导航到不同的视图。Mosby3保留演示者的实例。创建视图的新实例时,演示程序将被还原并附加到视图中。onStart()的新视图,演示者将更新意图。因此,新视图创建了新的意图,演示者将使用PublishSubject订阅它们。
如果前面的视图的意图发出了onComplete(),那么PublishSubject也完成了,流也关闭了。绑定到此意图的( intent )逻辑将被取消订阅。因此,这种意图不能再由视图触发。
在原始问题的例子中。Observable.just(true)关闭流。即使视图及其意图被重新创建(旋转后),也不会发出新项。相反,mReloadDataSubject.startWith(true)不发出onComplete(),流是t closed. When the presenter resubscribes to that intent (after rotation), the intent emits thestartsWith(真)`。在本例中,这将导致每次旋转时数据的完全重新加载。
为了触发条件重新加载的意图,RxNavi可能非常有用。
public Observable<Boolean> intentReloadData() {
//check if the data needs a reload in onResume()
return RxNavi.observe(this, Event.RESUME)
.filter(ignored -> mNeedsReload == true)
.map(ignored -> true);
}发布于 2017-02-20 14:32:49
Mosby MVI尊重反应性流合同。看看intentLoadData()
public Observable<Boolean> intentLoadData(){
return Observable.just(true);
}Observable.just(true)不仅调用onNext(true),而且还调用onCompleted()。一旦完成了一个反应流,就不能通过该流发出任何进一步的项。在onComplete()之后,可观测到的流将永久关闭。
在这种情况下,使用PublishSubject是完全可以的,但是为了更好的可读性,我建议不要使用startWith(),而是这样做:
public class MyActivity extends MviActivity<MyView, MailListViewState> {
private PublishSubject<Boolean> mReloadDataSubject = PublishSubject.create();
public void onResume(){
super.onResume();
// Triggers on screen orientation changes and
// when navigating back to this screen from back stack
mReloadDataSubject.onNext(true);
}
public Observable<Boolean> intentLoadData(){
return mReloadDataSubject;
}
}顺便说一句。您还可以使用像Trello的纳维这样的库,它为生命周期事件提供了可观察的流,但请记住,如果活动被破坏(即在屏幕方向更改期间),Navi会发出一个onCompleted()事件,因此您最终会遇到相同的情况:如果您想在以后再次触发意图,则必须确保不调用onCompleted()。
https://stackoverflow.com/questions/42345895
复制相似问题