2016-07-13 16 views
1

Ich habe eine Stunde Erfahrung mit RxJava und ich versuche, es in meinem Projekt zu implementieren, anstatt Schnittstellen und Listener zu verwenden.RxJava mit AsyncTask und Aktivität in android

Ich habe eine asynchrone Aufgabe, die eine Google Cloud-Endpunkt-Methode in einem separaten Modul aufruft und eine List<Profile> empfängt, wenn Sie fertig sind.

In der onPostExecute() Methode der asynchronen Task, rufe ich onNext auf, damit alle Teilnehmer diese Daten erhalten.

Hier ist, was die AsyncTask wie folgt aussieht:

private BirthpayApi mApi; 
private String mUserId; 
private ReplaySubject<List<Profile>> notifier = ReplaySubject.create(); 

public GetFriends(String userId) { 
    mUserId = userId; 
} 

public Observable<List<Profile>> asObservable() { 
    return notifier; 
} 

@Override 
protected List<Profile> doInBackground(Void... params) { 
    if (mApi == null) { 
     BirthpayApi.Builder builder = new BirthpayApi.Builder(AndroidHttp.newCompatibleTransport(), 
        new AndroidJsonFactory(), null) 
        // options for running against local devappserver 
        // - 10.0.2.2 is localhost's IP address in Android emulator 
        // - turn off compression when running against local devappserver 
        .setRootUrl("http://10.0.2.2:8080/_ah/api/") 
        .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() { 
        @Override 
        public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException { 
          abstractGoogleClientRequest.setDisableGZipContent(true); 
         } 
        }); 
      mApi = builder.build(); 
    } 

    try { 
     return mApi.getFriends(mUserId).execute().getItems(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 

@Override 
protected void onPostExecute(List<Profile> friends) { 
    super.onPostExecute(friends); 
    notifier.onNext(friends); 
} 

In meinem Fragment Ich möchte dann diese Daten aus dem die onNext() Methode aufrufen async Aufgabe sammeln. Ich verwende daher implements Action1<List<Profile>>, wenn ich meine Klasse deklariere, die auch Fragment erweitert.

Im onCall() Methode, die von der Action1 Schnittstelle kommt ich die Daten sammeln aus dem Async Aufgabe gesendet:

@Override 
public void call(List<Profile> profiles) { 
    if (profiles.size() > 0) { 
     updateAdapter(profiles); 
    } else 
     setUpNoFriendsViews(); 
} 

ich mit Treehouse folgenden bin zusammen, aber sie verwenden, um ein Objekt, ihre Daten zu modellieren, die die beobachtbare wird anstatt eine asynchrone Klasse zu verwenden und sie verwenden einen Adapter als Beobachter. Mache ich das falsch, wie bekomme ich es zur Arbeit?

+0

so wollen Sie Ihre beobachtbare eine aktualisierte Profilliste zu emittieren, wenn Sie Ihren Anruf? –

+0

Ja. @Will Evers –

+0

Dann möchten Sie eine Observable, die Ereignisse beobachtet, die Ihre Liste ändern würden und es in Ihre aktualisierte Liste abbildet, indem Sie Ihre API in einer Funktion aufrufen. dies asynchron zu tun, müssen Sie die RXbindings Bibliothek verwenden OR Anruf weiterhin verwenden Sie Ihren Async-Aufruf –

Antwort

5

Es sieht nicht so aus, als ob Sie das Observable abonnieren, das Sie irgendwo erstellen, und es ist nicht klar, wo Sie auf der AsyncTask aufrufen. Auch ich nicht denke Sie würden ein ReplaySubject wollen, aber das hängt davon ab, was Sie erreichen wollen.

Abgesehen davon würde ich vorschlagen, komplett auf Rx umzusteigen, anstatt Rx und AsyncTasks zu mischen. In diesem Fall in der Modellklasse macht eine Methode so etwas wie:

public Observable<List<Profile>> getProfiles() { 

    return Observable.defer(new Func0<Observable<List<Profile>>>() { 
     @Override 
     public Observable<List<Profile>> call() { 

      if (mApi == null) { 
       BirthpayApi.Builder builder = new BirthpayApi.Builder(AndroidHttp.newCompatibleTransport(), 
         new AndroidJsonFactory(), null) 
         // options for running against local devappserver 
         // - 10.0.2.2 is localhost's IP address in Android emulator 
         // - turn off compression when running against local devappserver 
         .setRootUrl("http://10.0.2.2:8080/_ah/api/") 
         .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() { 
          @Override 
          public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException { 
           abstractGoogleClientRequest.setDisableGZipContent(true); 
          } 
         }); 
       mApi = builder.build(); 
      } 

      try { 
       List<Profile> profiles = mApi.getFriends(mUserId).execute().getItems(); 
       return Observable.just(profiles); 
      } catch (IOException e) { 
       return Observable.error(e); 
      } 
     } 
    }); 
} 

Dann in Ihrem Fragmente:

modal.getProfiles() 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(
     new Action1<List<Profile>>() { 
       //... 
     }, 
     new Action1<Throwable>() { 
      @Override 
      public void call(Throwable throwable) { 
       throwable.printStackTrace(); 
      } 
     } 
    ); 
+0

Aber das ist nicht der empfohlene Weg. Wie würde der empfohlene Weg aussehen? Vielen Dank für die Antwort. @Jahnold –

+0

Wenn Sie "empfehlen" sagen, meinen Sie Treehouse empfohlen? Ich kann die Antwort erweitern, wenn Sie zeigen möchten, wie man ein Thema mit einer AsyncTask verwendet ... aber ich würde es nicht empfehlen! – Jahnold

+0

So würden Sie es tun. @Jahnold –