Android RxJava 2, subscribeOn 和 BehaviorSubject 留在 MainThread
Android RxJava 2, subscribeOn with BehaviorSubject stay on MainThread
我在 Android 中使用带有 RxJava2 的 BehaviourSubject。在以下链中,即使我订阅了(schedulers.background()),我也会收到 NetworkOnMainThreadException。
如果我在 searchRequestSubject 之后使用 ObserveOn(schedulers.background()),我会正确地进入后台线程。
我希望使用 subscribeOn 将所有链条放入提供的线程中?为什么它不是这样工作的?
private BehaviorSubject<SearchRequest> searchRequestSubject = BehaviorSubject.create();
searchRequestSubject
.doOnEach(responseNotification -> Logger.d("Current Thread1: "+Thread.currentThread()))
//.observeOn(schedulers.background()) // this is the current solution but
.flatMap(searchRequest -> adSearchService.getAds(searchRequest))
.doOnEach(responseNotification -> Logger.d("Current Thread2: "+Thread.currentThread()))
.doOnNext(apiResponse -> updateResponseSubject(apiResponse))
.doOnEach(responseNotification -> Logger.d("Current Thread3: "+Thread.currentThread()))
.subscribeOn(schedulers.background()) // this one should make the whole chain to subscribe on background. but it don't. why?
.subscribe()
// Logs //
Current Thread1: Thread[main,5,main]
Current Thread2: Thread[main,5,main]
Current Thread3: Thread[main,5,main]
网络调用
public Observable<ApiResponse> getAds(@NonNull SearchRequest adRequest){
if (adRequest == null){
throw new IllegalStateException("Search Request should never be null");
}
return apiService.getAdsObservable(token, adRequest.pageNumber(), adRequest.resultsNumberByPage(), adRequest.presentation(),
adRequest.toLatLongQuery(), adRequest.isClosed(), adRequest.toAdTypeQuery(), adRequest.category(),
adRequest.keywords(),adRequest.radius(), adRequest.from(), adRequest.to(), adRequest.isReserved(), adRequest.adId())
.map(response -> handleResponseCode(response, adRequest.location()))
.onErrorReturn(error -> errorHandling.handleError(error));
}
private ApiResponse handleResponseCode(Response<AdResponse> response, Location location) {
if (response.isSuccessful()){
return AdSearchResponse.Response.create(response.body(), location);
} else if (response.code() == 404){
return AdSearchResponse.NotFoundError.create();
} else {
return errorHandling.handleError(response, null);
}
}
ApiService由Retrofit 2提供
@AutoValue
public abstract class AppSchedulers {
public abstract Scheduler UI(); // AndroidSchedulers.mainThread()
public abstract Scheduler background(); // Schedulers.io()
// [...] creator and builder
}
实际上这是因为您使用的是热可观察对象 (BehaviorSubject),除非您使用的是 observeOn,否则您将停留在执行 onNext 的线程上。 subscribeOn 大部分时间用于冷可观察对象。所以在你的情况下:
searchRequestSubject
.observeOn(schedulers.background())
.doOnEach(responseNotification -> Logger.d("Current Thread1: "+Thread.currentThread()))
.flatMap(searchRequest -> adSearchService.getAds(searchRequest))
.doOnEach(responseNotification -> Logger.d("Current Thread2: "+Thread.currentThread()))
.doOnNext(apiResponse -> updateResponseSubject(apiResponse))
.doOnEach(responseNotification -> Logger.d("Current Thread3: "+Thread.currentThread()))
.subscribe()
检查 link,转到 ObserveOn 部分:http://tomstechnicalblog.blogspot.ca/2016/02/rxjava-understanding-observeon-and.html
你的onNext就像一个点击动作
在愤怒、沮丧和单元测试之后表明这不是由于可观察到的热/冷问题。我已经清理了构建。重新启动 Android Studio。再次构建,它按预期工作,没有任何更改。
总是Clean/Rebuild有任何疑问...
我在 Android 中使用带有 RxJava2 的 BehaviourSubject。在以下链中,即使我订阅了(schedulers.background()),我也会收到 NetworkOnMainThreadException。
如果我在 searchRequestSubject 之后使用 ObserveOn(schedulers.background()),我会正确地进入后台线程。
我希望使用 subscribeOn 将所有链条放入提供的线程中?为什么它不是这样工作的?
private BehaviorSubject<SearchRequest> searchRequestSubject = BehaviorSubject.create();
searchRequestSubject
.doOnEach(responseNotification -> Logger.d("Current Thread1: "+Thread.currentThread()))
//.observeOn(schedulers.background()) // this is the current solution but
.flatMap(searchRequest -> adSearchService.getAds(searchRequest))
.doOnEach(responseNotification -> Logger.d("Current Thread2: "+Thread.currentThread()))
.doOnNext(apiResponse -> updateResponseSubject(apiResponse))
.doOnEach(responseNotification -> Logger.d("Current Thread3: "+Thread.currentThread()))
.subscribeOn(schedulers.background()) // this one should make the whole chain to subscribe on background. but it don't. why?
.subscribe()
// Logs //
Current Thread1: Thread[main,5,main]
Current Thread2: Thread[main,5,main]
Current Thread3: Thread[main,5,main]
网络调用
public Observable<ApiResponse> getAds(@NonNull SearchRequest adRequest){
if (adRequest == null){
throw new IllegalStateException("Search Request should never be null");
}
return apiService.getAdsObservable(token, adRequest.pageNumber(), adRequest.resultsNumberByPage(), adRequest.presentation(),
adRequest.toLatLongQuery(), adRequest.isClosed(), adRequest.toAdTypeQuery(), adRequest.category(),
adRequest.keywords(),adRequest.radius(), adRequest.from(), adRequest.to(), adRequest.isReserved(), adRequest.adId())
.map(response -> handleResponseCode(response, adRequest.location()))
.onErrorReturn(error -> errorHandling.handleError(error));
}
private ApiResponse handleResponseCode(Response<AdResponse> response, Location location) {
if (response.isSuccessful()){
return AdSearchResponse.Response.create(response.body(), location);
} else if (response.code() == 404){
return AdSearchResponse.NotFoundError.create();
} else {
return errorHandling.handleError(response, null);
}
}
ApiService由Retrofit 2提供
@AutoValue
public abstract class AppSchedulers {
public abstract Scheduler UI(); // AndroidSchedulers.mainThread()
public abstract Scheduler background(); // Schedulers.io()
// [...] creator and builder
}
实际上这是因为您使用的是热可观察对象 (BehaviorSubject),除非您使用的是 observeOn,否则您将停留在执行 onNext 的线程上。 subscribeOn 大部分时间用于冷可观察对象。所以在你的情况下:
searchRequestSubject
.observeOn(schedulers.background())
.doOnEach(responseNotification -> Logger.d("Current Thread1: "+Thread.currentThread()))
.flatMap(searchRequest -> adSearchService.getAds(searchRequest))
.doOnEach(responseNotification -> Logger.d("Current Thread2: "+Thread.currentThread()))
.doOnNext(apiResponse -> updateResponseSubject(apiResponse))
.doOnEach(responseNotification -> Logger.d("Current Thread3: "+Thread.currentThread()))
.subscribe()
检查 link,转到 ObserveOn 部分:http://tomstechnicalblog.blogspot.ca/2016/02/rxjava-understanding-observeon-and.html 你的onNext就像一个点击动作
在愤怒、沮丧和单元测试之后表明这不是由于可观察到的热/冷问题。我已经清理了构建。重新启动 Android Studio。再次构建,它按预期工作,没有任何更改。
总是Clean/Rebuild有任何疑问...