2017-12-22 4 views
1
swipeRefreshLayout.setOnRefreshListener(() -> { 
swipeRefreshLayout.setRefreshing(true); 
retrieveData(mCardAdapter, db); 
}); 

Aus irgendeinem Grund blockiert die folgende Methode mein Haupt-UI-Thread, aber es sollte im Hintergrund ausgeführt werden. Zum Beispiel hängt die Aktualisierungsanzeige, wenn ich retrieveData() ausführen. Wenn ich vor der Ausführung einen Fortschrittsdialog initialisiere, hängt es auch und ich kann nicht durch meine RecyclerView scrollen. Verstehe ich hier etwas grundsätzlich falsch?Ruft meine Retrofit/ReactiveX-Methode tatsächlich Daten asynchron ab?

public void retrieveData(final CardAdapter mCardAdapter, SQLiteHelper db) { 
CausticRetrofitService service = ServiceFactory.createRetrofitService(CausticRetrofitService.class, CausticRetrofitService.SERVICE_ENDPOINT); 
service.getMedia() 
    .subscribeOn(Schedulers.newThread()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(new Subscriber <MediaResponse>() { 
    @Override 
    public final void onCompleted() { 

    Log.e("CausticRetrofitService", "Caustic Request Completed!"); 

    /* Cancel all progress indicators after data retrieval complete */ 
    setRefreshingFalse(); 

    // TODO: Add media to local data store and then display them one-by-one in real-time 
    mCardAdapter.addData(db.getAllMediaImages()); // Add all media images to card views 
    Log.d(getClass().toString(), "Added to local database: " + db.getAllMediaImages()); 
    mCardAdapter.notifyDataSetChanged(); 
    } 

    @Override 
    public final void onError(Throwable e) { 
    /* Cancel all progress indicators on data retrieval error */ 
    setRefreshingFalse(); 

    Toast.makeText(getApplicationContext(), "Cannot retrieve data. Please try again later.", Toast.LENGTH_SHORT).show(); 
    Log.e("CausticRetrofitService", e.getMessage()); 
    } 

    @Override 
    public final void onNext(MediaResponse mediaResponse) { 
    if (mediaResponse != null) { 

    Log.e("CausticRetrofitService", "Returned objects: " + mediaResponse.getResults()); 

    for (String mediaId: mediaResponse.getResults()) { 
     Log.e("CausticRetrofitService", mediaId); 
    } 

    List <String> mediaIds = mediaResponse.getResults(); 
    Log.d(getClass().toString(), "All Media IDs: " + mediaIds); 

    if (mediaIds.isEmpty()) { 
     Toast.makeText(getApplicationContext(), "Cannot retrieve data. Please try again later.", Toast.LENGTH_SHORT).show(); 
    } 

    mCardAdapter.clear(); 
    mCardAdapter.notifyDataSetChanged(); 

    /* Store objects from remote web service to local database */ 
    for (String mediaId: mediaIds) { 
     // TODO: Why are these null? 
     Log.d(getClass().toString(), "Media Id: " + mediaId); 
     MediaImage newMediaImage = new MediaImage(); 
     newMediaImage.setTitle(mediaId); 
     db.addMediaImage(newMediaImage); // Add media image to local database 
    } 

    } else { 
    Log.e("CausticRetrofitService", "Object returned is null."); 
    } 

    } 

    }); 
} 

Ich denke, dass an dem lokalen Datenspeicher in den onNext() Verfahren die Datenfern Hinzufügen könnte die Sache, das ist blockiert, obwohl ich nicht sicher bin.

Antwort

1

Ihr Netzwerk Anruf wird in einem neuen Thread getan, wie Sie festgelegt, aber die Teilnehmer Methoden onNext() und onComplete() läuft auf der Beobachtung Scheduler, die den Haupt-Thread ist.

Sie scheinen einige Datenbankoperationen auf diesen durchzuführen, versuchen Sie, die Zwischenspeicherung auch auf den Hintergrund Thread mit einem Operator doOnNext() zu entladen.

Was doOnNext() tun kann, ist, dass es für jede Emission in Ihrem Stream aufgerufen wird.

Es etwas wie das

service.getMedia() 
    .doOnNext(data -> cacheData(data)) 
    .subscribeOn(Schedulers.newThread()) 
    .observeOn(AndroidSchedulers.mainThread()) 

Wo cacheData() ist eine Methode gehen, dass Ihr alle Anrufe DB tut. Und die einzigen Dinge, die in Ihrem onNext() und onComplete() übrig sind, würden nur die UI aktualisieren.

Verwandte Themen