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

다음과 같은 방법으로 내 기본 UI 스레드가 차단되지만 백그라운드에서 실행 중이어야합니다. 예를 들어 retrieveData()을 실행하면 새로 고침 표시기가 멈 춥니 다. 실행하기 전에 진행 대화 상자를 초기화하면 멈추고 RecyclerView를 스크롤 할 수 없습니다. 나는 근본적으로 여기서 뭔가를 오해하고 있는가? 나는 확실하지 않다 있지만 onNext() 방법으로 로컬 데이터 저장소에 원격 데이터를 추가하는 것은 차단 년대 일이 될 수 있음을 생각하고내 Retrofit/ReactiveX 메소드가 실제로 데이터를 비동기로 검색합니까?

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."); 
    } 

    } 

    }); 
} 

.

답변

1

네트워크 호출이 지정한 새 스레드에서 수행되었지만 구독자 메서드 onNext()onComplete()은 주 스레드 인 관찰 Scheduler에서 실행됩니다.

이러한 데이터베이스 작업을 수행하는 것처럼 보이지만 doOnNext() 연산자를 사용하여 백그라운드 스레드에 캐싱을 오프로드하십시오.

무엇을 doOnNext()이 수행 할 것인지는 스트림에서 각 방출에 대해 호출된다는 것입니다.

그것은 그

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

)처럼 뭔가를 갈 수있는 것은 모든 DB 호출을 수행하는 방법이다. onNext()onComplete()에 남아있는 유일한 것은 UI 만 업데이트하는 것입니다.