2016-09-08 12 views
1

我想學習RxJava,我正在轉換AsyncTask我必須成爲Observable/Subscriber。原始AsyncTask在後臺加載圖像,然後在onPostExecute中將ImageView的drawable設置爲加載的圖像。顯示的圖像位於回收站視圖中,當列表滾動時,將爲列表中的每個項目加載一張圖像。我將它轉換爲Rx,但現在滾動時存在很多延遲。每次調用fetchThumbnail的方法onBind在RecyclerView的適配器中調用。下面你會看到我的原始實現註釋掉了,還有新的實現。使用RxJava時,內存或CPU使用率沒有明顯增加。我相信我正在訂閱並觀察正確的主題。是什麼賦予了?將圖像加載asynctask轉換爲rxjava,爲什麼它滯後於用戶界面?

public class ThumbnailWorker { 

    public static void fetchThumbnail(final Context context, final GalleryItem galleryItem, final int thumbId, final ThumnailFetchedListener completionListener) { 

     galleryItem.thumbnail.setImageBitmap(null); 
     galleryItem.progressBar.setVisibility(View.VISIBLE); 

     Observable.just(MediaStore.Video.Thumbnails.getThumbnail(context.getContentResolver(), 
       thumbId 
       , MediaStore.Video.Thumbnails.MINI_KIND, 
       null)) 
       .subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(new Action1<Bitmap>() { 
        @Override 
        public void call(Bitmap bitmap) { 
         completionListener.thumbnailFetched(galleryItem, bitmap, thumbId); 
         galleryItem.progressBar.setVisibility(View.GONE); 
        } 
       }); 


// 
//  new AsyncTask<Void,Bitmap,Bitmap>() { 
// 
// 
//   @Override 
//   protected void onPreExecute() { 
//    super.onPreExecute(); 
//    galleryItem.thumbnail.setImageBitmap(null); 
//    galleryItem.progressBar.setVisibility(View.VISIBLE); 
//   } 
// 
//   @Override 
//   protected Bitmap doInBackground(Void... params) { 
//    Bitmap bitmap = MediaStore.Video.Thumbnails.getThumbnail(context.getContentResolver(), 
//      thumbId 
//      ,MediaStore.Video.Thumbnails.MINI_KIND, 
//      null 
//    ); 
// 
//    return bitmap; 
//   } 
// 
// 
//   @Override 
//   protected void onPostExecute(Bitmap bitmap) { 
//    super.onPostExecute(bitmap); 
//    completionListener.thumbnailFetched(galleryItem, bitmap,thumbId); 
//    galleryItem.progressBar.setVisibility(View.GONE); 
// 
//   } 
//  }.execute(); 


    } 
} 

這是所有聽衆做。偵聽器回調到適配器。

@Override 
public void thumbnailFetched(GalleryItem item, Bitmap thumbnail, int thumbId) { 
    if(thumbId == item.id) { 
     item.thumbnail.setImageBitmap(thumbnail); 
    } 
} 
+0

如果有一件事,你似乎沒有在任何地方退訂。 – EpicPandaForce

回答

1

UI阻塞的原因是just(...)運算符中的表達式在當前線程中執行。

如果你想在你的subscribeOn(..)指定的線程來執行表達式,那麼你必須創建Observable使用create(..)方法,而不是just(..)之一。

對你來說應該是這樣的:

Observable.create(new Observable.OnSubscribe<Bitmap>(){ 
     @Override 
     public void call(Subscriber<? super Bitmap> subscriber){ 
      subscriber.onNext(MediaStore.Video.Thumbnails.getThumbnail(context.getContentResolver(), 
        thumbId 
        , MediaStore.Video.Thumbnails.MINI_KIND, 
        null)); 

      subscriber.onCompleted(); 
     } 
    }) 
      .subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new Action1<Bitmap>() { 
       @Override 
       public void call(Bitmap bitmap) { 
        completionListener.thumbnailFetched(galleryItem, bitmap, thumbId); 
        galleryItem.progressBar.setVisibility(View.GONE); 
       } 
      }); 
+3

使用'Observable.create'可以減輕錯誤處理和背壓的負擔。 'fromCallable'是一個更加優雅的解決方案。 – npace

+0

我同意。 @dwursteisen的答案更加優雅。但是你必須記住'fromCallable()'不會共享訂閱者之間的結果(發送),它會爲每個新訂閱者執行傳遞函數。 –

+0

好點!我對Rx還是一個新鮮的東西,但是不會將一個調用鏈接到'cache()'補救這種行爲? – npace

4

Observable.just可用於已經計算的值。

我假設這個電話MediaStore.Video.Thumbnails.getThumbnail(...)處理你的圖像,所以可能會滯後你的用戶界面。你必須推遲你的電話。要做到這一點,你可以用Observable.fromCallable

Observable.fromCallable(() -> MediaStore.Video.Thumbnails.getThumbnail(context.getContentResolver(), thumbId     , MediaStore.Video.Thumbnails.MINI_KIND, null)) 
      .subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(bitmap -> { 
        completionListener.thumbnailFetched(galleryItem, bitmap, thumbId); 
        galleryItem.progressBar.setVisibility(View.GONE); 
      }); 
+0

延遲調用的含義是什麼?這是否意味着呼叫的背景? –

+0

在您訂閱observable時執行調用,而不是在創建observable時 – dwursteisen