我正在努力理解如何正确使用RxBinding
,如果我想在用户向下刷SwipeRefreshLayout
时调用网络请求,我希望能说出像
RxSwipeRefreshLayout.refreshes(swipeContainer)
.flatMap { networkRequest() }
.subscribeBy(
onNext = { list: List<Data> -> Timber.d(data) },
onError = { showErrorSnackbar(it) },
onComplete = { Timber.d("On Complete") })
但是这对我来说不起作用,因为我把它包含在一个名为setupSwipeRefresh()
的函数中,我在onStart
中调用它,所以一旦onStart
被调用,就会发出网络请求,因为那是布局订阅的时候。
现在我不确定该怎么做。我可以把整个事情放在refreshListener
但这种方式击败了RxBinding
的目的。
或者我可以在networkRequest
的onNext
执行swipeContainer
。但那时看起来就像是
RxSwipeRefreshLayout.refreshes(swipeContainer)
.subscribeBy(
onNext = {
networkRequest()
.subscribeBy(
onNext = { list: List<Data> ->
Timber.d(data)
})
},
onError = { showErrorSnackbar(it) },
onComplete = { Timber.d("On Complete") })
但是两次调用subscribe似乎就像反模式一样,所以是的,因为SwipeRefreshLayout
在RxBinding
库中,必须有一种惯用的方法,因为它似乎是最常见的用例。
你正在寻找这样的东西:
SwipeRefreshLayout viewById = findViewById(R.id.activity_main_swipe_refresh_layout);
Observable<State> swipe = RxSwipeRefreshLayout.refreshes(viewById)
.map(o -> new IsLoading());
Observable<State> stateObservable = Observable.<State>just(new IsLoading())
.mergeWith(swipe)
.switchMap(state -> Observable.concat(
Observable.just(new IsLoading()),
Observable.<State>timer(500, TimeUnit.MILLISECONDS)
.map(aLong -> new LoadingResult(Collections.emptyList())
)
)
).distinct();
stateObservable
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
state -> {
if (state instanceof IsLoading) {
Log.d("state", "isLoading");
} else if (state instanceof LoadingResult) {
Log.d("state", "loadingResult");
viewById.setRefreshing(false);
}
});
活动
interface State { }
class IsLoading implements State { }
class LoadingResult implements State {
private final List<String> result;
public LoadingResult(List<String> result) {
this.result = result;
}
}
SwitchMap与FlatMap类似,但它将切换到新的可观察对象并丢弃来自previouse observable的事件。