2015-08-14 4 views
5

Okay, also habe ich ein bisschen Probleme mit einem RxJava Observable, das ich in meiner Android App verwende. Es ist extrem frustrierend, weil das schon eine ganze Weile funktioniert hat und jetzt erst den obigen Fehler auslöst. Ich bin mir bewusst, dass dies bedeutet, dass ich eine UI-Operation von einem anderen Thread aus mache, aber ich sehe nicht, wo das passiert. So, hier ist der beobachtbare:RxJava Kann keinen Handler innerhalb des Threads erstellen, der Looper.prepare() nicht aufgerufen hat

ConnectionsList.getInstance(this).getConnectionsFromParse(mCurrentUser) 
      .delay(3, TimeUnit.SECONDS) 
      .flatMap(s -> mainData.getDataFromNetwork(this, mCurrentUser, mSimpleFacebook)) 
      .flatMap(s -> mainData.getPictureFromUrl(s)) 
      .subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new Observer<Bitmap>() { 
       @Override 
       public void onCompleted() { 
        if (mCurrentUser.get(Constants.NAME) != null) { 
         mNavNameField.setText((String) mCurrentUser.get(Constants.NAME)); 
        } 
        mSearchFragment.setupActivity(); 
       } 

       @Override 
       public void onError(Throwable e) { 
        e.printStackTrace(); 
        mSearchFragment.setEmptyView(); 
       } 

       @Override 
       public void onNext(Bitmap bitmap) { 
        mNavProfImageField.setImageBitmap(bitmap); 
        mainData.saveImageToParse(bitmap); //save the image to Parse backend 
       } 
      }); 

Nach einigen Debuggen fand ich, dass dieser flatmap ist, wo der Fehler passiert:

.flatMap(s -> mainData.getDataFromNetwork(this, mCurrentUser, mSimpleFacebook)) 

Innerhalb von etwa folgender: Ich habe einen Kommentar, wo der Fehler hinzugefügt wird geworfen:

return Observable.create(subscriber -> { 
      //set the username field if ParseUser is not null 
      if(currentUser != null) { 
       username = (String) currentUser.get(Constants.NAME); 
      } 

      //if prof pic is null then request from facebook. Should only be on the first login 
      if (currentUser != null && currentUser.getParseFile(Constants.PROFILE_IMAGE) == null) { 
       if (AccessToken.getCurrentAccessToken() != null) { //check if session opened properly 
        //get simple facebook and add the user properties we are looking to retrieve 
        Profile.Properties properties = new Profile.Properties.Builder() 
          .add(Profile.Properties.FIRST_NAME) 
          .add(Profile.Properties.GENDER) 
          .add(Profile.Properties.BIRTHDAY) 
          .add(Profile.Properties.ID) 
          .add(Profile.Properties.EMAIL) 
          .build(); 

        //The following line is where the debugger stops 
        //and the error gets thrown 
        simpleFacebook.getProfile(properties, new OnProfileListener() { 
         @Override 
         public void onComplete(Profile response) { 
          String id = response.getId(); 
          String name = response.getFirstName(); 
          String gender = response.getGender(); 
          String birthday = response.getBirthday(); 
          String email = response.getEmail(); 
          String age = getAge(birthday); 

          currentUser.put(Constants.NAME, name); 
          currentUser.put(Constants.AGE, age); 
          currentUser.put(Constants.GENDER, gender); 
          currentUser.put(Constants.EMAIL, email); 
          currentUser.saveInBackground(); 

          if (id != null) { //display the profile image from facebook 
           subscriber.onNext("https://graph.facebook.com/" + id + "/picture?type=large"); 
          } 
         } 

Was geht hier vor? Es funktioniert gut wie es ist und jetzt sagt es, dass ich auf einem Hilfs-Thread bin. Soweit es mich betrifft, war ich bis jetzt auf dem UI-Thread. Wenn jemand mir helfen kann, wäre das großartig, sonst muss ich RxJava vorerst fallen lassen, da es für mich nicht klappt. Danke im Voraus!

+0

Ich vermute, das Problem ist das: '.subscribeOn (Schedulers.io())'. Sie sollten den Haupt-Thread-Scheduler abonnieren, da Ihre Netzwerkoperationen asynchron zu sein scheinen. – corsair992

+0

Könnten Sie den Stack-Trace veröffentlichen? Liegt es daran, dass 'getProfile' im Hauptthread aufgerufen werden muss? – zsxwing

+0

Ich vermute, dass getprofile auf den Hauptthread aufgerufen werden muss, aber es verwirrt mich nicht, warum es vorher funktioniert hat. Sollte ich subscribeOn (AndroidSchedulers.MainThread) haben? –

Antwort

0

Es sieht aus wie der simpleFacebook.getProfile(properties, listener) Aufruf ist es eigene Threading intern. Normalerweise möchten Sie dies nicht mit rxjava. Sie möchten, dass rxjava sich um das Threading kümmert, und der gesamte Code, den Sie schreiben, sollte synchron sein.

Ich bin nicht mit dem Facebook SDK vertraut, aber ich würde nach einem Anruf suchen, der die Anfrage synchron ausführt. Also eine Methode, die aussieht wie public Profile getProfile(Properties properties) { anstelle von einer, die void zurückgibt und einen Listener benötigt.

Hoffe, das hilft ..