2015-10-31 6 views
8

I Retrofit mit RxJava in meinem Android-App verwenden, und mein Code:Retrofit Standard-Thread

public void getConfig(NetworkSubscriber subscriber) { 
    Observable<Config> observable = mApi.getConfig(); 
    observable.subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(subscriber); 
} 

public void getCode(String mobile, int type, NetworkSubscriber subscriber) { 
    Observable<BaseMessageEntity> observable = mApi.getCode(mobile, type); 
    observable.subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(subscriber); 
} 

Und ich will nicht .subscribeOn(Schedulers.newThread()) und .observeOn(AndroidSchedulers.mainThread()) jedes Unternehmen Methode

Wie kann ich tun, um schreiben ?

Antwort

17

Wenn Sie die Threads, die Sie bei jedem Aufruf möchten, nicht angeben möchten, können Sie einen Wrapper um RxJavaCallAdapterFactory erstellen, um standardmäßig Ihre Threads für Sie festzulegen.

public class RxThreadCallAdapter extends CallAdapter.Factory { 

    RxJavaCallAdapterFactory rxFactory = RxJavaCallAdapterFactory.create(); 
    private Scheduler subscribeScheduler; 
    private Scheduler observerScheduler; 

    public RxThreadCallAdapter(Scheduler subscribeScheduler, Scheduler observerScheduler) { 
     this.subscribeScheduler = subscribeScheduler; 
     this.observerScheduler = observerScheduler; 
    } 

    @Override 
    public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { 
     CallAdapter<Observable<?>> callAdapter = (CallAdapter<Observable<?>>) rxFactory.get(returnType, annotations, retrofit); 
     return callAdapter != null ? new ThreadCallAdapter(callAdapter) : null; 
    } 

    final class ThreadCallAdapter implements CallAdapter<Observable<?>> { 
     CallAdapter<Observable<?>> delegateAdapter; 

     ThreadCallAdapter(CallAdapter<Observable<?>> delegateAdapter) { 
      this.delegateAdapter = delegateAdapter; 
     } 

     @Override public Type responseType() { 
      return delegateAdapter.responseType(); 
     } 

     @Override 
     public <T> Observable<?> adapt(Call<T> call) { 
      return delegateAdapter.adapt(call).subscribeOn(subscribeScheduler) 
       .observeOn(observerScheduler); 
     } 
    } 
} 

und dann verwenden, statt RxJavaCallAdapterFactory.create() in Ihrem builder -

Retrofit retrofit = new Retrofit.Builder() 
    .baseUrl("https://api.github.com/") 
    .addConverterFactory(GsonConverterFactory.create()) 
    .addCallAdapterFactory(new RxThreadCallAdapter(Schedulers.io(), AndroidSchedulers.mainThread())) 
    .build(); 
+0

Denkt an Bruder! Du hast mich! – xuyanjun

+0

Dieser Fehler, wenn Sie innerhalb der Threads aufrufen (IE benutzerdefinierte Zugriffsverwaltung) '' 'zurück delegateAdapter.responseType();' '' wird Nullzeiger zurückgeben. –

6

Sie können es unter Verwendung von compose() auf eine Zeile reduzieren. Zum Beispiel ist unten eine modifizierte Version Ihrer getConfig() Methode. Es setzt voraus, dass Sie RetroLambda verwenden.

public void getConfig(NetworkSubscriber subscriber) { 
    Observable<Config> observable = mApi.getConfig(); 
    observable 
      .compose(this::setupThreads) 
      .subscribe(subscriber); 
} 

Die setupThreads() Methode würde wie folgt aussehen:

private <T> Observable<T> setupThreads(final Observable<T> observable) { 
    return observable 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()); 
} 

Einige Referenzen:

+0

danke, ich habe es. aber das ist keine Möglichkeit, es durch rx selbst zu lösen? – xuyanjun

+0

@xuyanjun - 'komponieren()' ist ein wertvoller Teil von RxJava, also bin ich mir nicht ganz sicher, was du mit "löse es durch rx selbst" meinst. In diesem Fall können Sie mit 'compose()' 'setupThreads() 'immer wieder verwenden, ohne' .subscribeOn (Schedulers.newThread()) hinzufügen zu müssen. ObserveOn (AndroidSchedulers.mainThread()) 'zu allen Observablen . – kjones

6

Um einen Standard-Scheduler für subscribeOn haben Sie es als Argument gerade zum RxJavaCallAdapterFactory passieren können, wenn Ihre Retrofit Instanz erstellen:

new Retrofit.Builder() 
      .client(okHttpClient) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io())) 
      .build(); 

Got in Retrofit eingeführt 2.0.0