【问题标题】:Android RxJava 2, subscribeOn with BehaviorSubject stay on MainThreadAndroid RxJava 2,带有 BehaviorSubject 的 subscribeOn 留在 MainThread
【发布时间】:2017-04-20 21:40:41
【问题描述】:

我在 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
}

【问题讨论】:

  • 您是否尝试过不是subscribe(),而是使用其他带参数的兄弟姐妹?
  • 是的,为了清楚起见,我已经删除了订阅中的数据
  • 正如我(已删除)的答案中所说,您的代码对我有用。所以我猜你的网络请求应该有问题

标签: android rx-java2


【解决方案1】:

实际上这是因为您使用的是热可观察对象(BehaviorSubject),除非您使用observeOn,否则您将留在执行onNext 的线程上。 subscribeOn 将大部分时间用于冷的 observables。所以在你的情况下:

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()

检查该链接,转到 ObserveOn 部分:http://tomstechnicalblog.blogspot.ca/2016/02/rxjava-understanding-observeon-and.html 你的 onNext 就像一个点击动作

【讨论】:

    【解决方案2】:

    经过愤怒、沮丧和单元测试表明这不是由于可观察到的热/冷问题。我已经清理了构建。重新启动 Android Studio。再次构建,它按预期工作,没有任何更改。

    如有任何疑问,请务必清理/重建...

    【讨论】:

      猜你喜欢
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 2017-09-15
      • 2019-05-26
      相关资源
      最近更新 更多