2017-04-19 5 views
0

Ich benutze ein BehaviourSubject mit RxJava2 in Android. In dieser folgenden Kette erhalte ich eine NetworkOnMainThreadException, selbst wenn ich subscribeOn (schedulers.background()) bin.Android RxJava 2, subscribeOn mit BehaviorSubject bleib auf MainThread

Wenn ich ObserveOn (schedulers.background()) direkt nach dem searchRequestSubject verwende, gehe ich richtig in einen Hintergrund-Thread.

Ich erwarte, dass die Verwendung von subscribeOn die gesamte Kette in den bereitgestellten Thread bekommen wird? Warum funktioniert es nicht so?

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] 

Netzwerk Anruf

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 durch Retrofit bereitgestellt 2

@AutoValue 
public abstract class AppSchedulers { 
    public abstract Scheduler UI(); // AndroidSchedulers.mainThread() 
    public abstract Scheduler background(); // Schedulers.io() 
    // [...] creator and builder 
} 
+0

Haben Sie mit nicht 'subscribe versucht()' aber mit anderen Geschwistern, die nimmt Parameter? – azizbekian

+0

Ja, ich habe die Daten im Abonnement für die Klarheit entfernt –

+0

Wie in meiner (gelöschten) Antwort gesagt, funktioniert Ihr Code für mich. Es sollte also etwas Falsches in Ihrer Netzwerkanfrage sein, denke ich – GVillani82

Antwort

1

Eigentlich ist es, weil Sie einen heißen beobachtbar (BehaviorSubject) verwenden, und es sei denn, Sie sind Mit einem observationOn bleiben Sie auf dem Thread, der onNext getan hat. subscribeOn wird meistens für kalte Observablen verwendet. Also in Ihrem Fall:

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

Überprüfen Sie, ob Link finden Sie auf der ObserveOn Abschnitt: http://tomstechnicalblog.blogspot.ca/2016/02/rxjava-understanding-observeon-and.html Ihre OnNext ist wie ein Klick-Aktion

0

Nach Wut, Frustration und Unit-Tests, die zeigt, dass es nicht durch ist zu ein heiß/kalt beobachtbares Problem. Ich habe den Build gereinigt. Android Studio wurde neu gestartet. Erneut erstellen und es funktionierte wie erwartet ohne Änderungen.

immer sauber/neu erstellen, wenn Zweifel ...

Verwandte Themen