简体   繁体   English

在MVI中访问reducer函数之外的状态

[英]Accessing state outside of reducer function in MVI

In MVI with the Mosby library, what is the best way to access the state outside of the reducer function in the stream? 在使用Mosby库的MVI中,访问流中reducer函数之外的状态的最佳方法是什么? For example, when you need to load the next page for your recycler, you need to know which page was loaded last. 例如,当您需要为回收器加载下一页时,您需要知道最后加载了哪个页面。 (In the sample app the last page is saved in the loader but that defeats the whole purpose of having a single state POJO) (在示例应用程序中,最后一页保存在加载程序中,但这违背了拥有单个状态POJO的全部目的)

There are multiple ways to do that and depending on how your pagination url is constructed, you may not need a reference to the privous state at all. 有多种方法可以做到这一点,并且根据您的分页URL的构造方式,您可能根本不需要引用私有状态。

For example let's say that you can access next page via a number. 例如,假设您可以通过数字访问下一页。 So the http request looks like this: http://www.foo.com/feed?page=1 next page is http://www.foo.com/feed?page=2 and so on. 所以http请求看起来像这样: http://www.foo.com/feed?page=1http://www.foo.com/feed?page=1 page http://www.foo.com/feed?page=1下一页是http://www.foo.com/feed?page=2等等。

Then you can basically do something like this: 那你基本上可以这样做:

Observable<Integer> nextPageIntent = intent(YourView::loadNextPageIntent)
                                    .scan(1, (previousPage, ignored) -> previousPage + 1);

Observable<State> state = nextPageIntent.switchMap(page -> backend.loadPage(page).map(...) )
                                        .startWith(...)
                                        .onErrorReturn(...);

So the trick is to add some "counter". 所以诀窍是添加一些“反击”。 Whenever YourView::loadNextPageIntent is triggered, we increment the page by one in .scan(1, (previousPage, ignored) -> previousPage + 1) . 每当触发YourView::loadNextPageIntent ,我们在.scan(1, (previousPage, ignored) -> previousPage + 1)中将page增加.scan(1, (previousPage, ignored) -> previousPage + 1) So this basically emits 1, 2, 3, 4, 5, ... and then loads the corresponding page from your backend. 所以这基本上会发出1, 2, 3, 4, 5, ...然后从你的后端加载相应的页面。

However, if you really need a reference to your previous state to determine the next page url you can model your state reducer slightly differently by using a BehaviorSubject instead of .scan() operator like this (cretits Paco Estevez ): 但是,如果你真的需要引用你以前的状态来确定下一个页面url,你可以通过使用BehaviorSubject而不是像这样的.scan()运算符(cretits Paco Estevez )来略微改变你的状态.scan()器的模型:

BehaviorSubject<State> state = BehaviorSubject.createDefault(initialState);
state.switchMap( oldState ->
        intent(YourView::loadNextPageIntent)
               .switchMap( ignored -> backend.loadPage(oldState.nextPageUrl) // You can access oldState now
                            .map(...))
                            .startWith(...)
                            .onErrorReturn(...)
).subscribe(state);


subscribeViewState(state, YourView::render)

The trick here is that you use a Subject which subscribes to itself. 这里的诀窍是你使用一个订阅自己的主题。 Basically it is the very similar to what .scan() operator does to implement a reducer but now you have the reference to the old state. 基本上它与.scan()运算符实现减速器非常相似,但现在您可以引用旧状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM