将图像加载异步任务转换为 rxjava,为什么它滞后 ui?
Converting an image loading asynctask to rxjava, why is it lagging the ui?
我正在尝试学习 RxJava,我正在转换 AsyncTask
我必须成为 Observable/Subscriber。原来的 AsyncTask
在后台加载了一张图片,然后在 onPostExecute
中将 ImageView 的可绘制对象设置为加载的图片。显示的图像在回收视图中,随着列表滚动,为列表中的每个项目加载图像。我将它转换为 Rx,但现在滚动时有很多延迟。每次在 RecyclerView 的适配器中调用 onBind
时都会调用方法 fetchThumbnail
。下面你会看到我原来的实现被注释掉了,还有新的实现。使用 RxJava 时,我没有发现内存或 cpu 使用量有显着增加。我相信我也在订阅和观察正确的线程。给出了什么?
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);
}
}
UI阻塞的原因是just(...)
运算符中的表达式是在当前线程中执行的
如果要在 subscribeOn(..)
中指定的线程中执行表达式,则必须使用 create(..)
方法创建 Observable
,而不是 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);
}
});
Observable.just
可用于已计算的值。
我假设此调用 MediaStore.Video.Thumbnails.getThumbnail(...)
处理您的图像,因此可能会滞后于您的 UI。你必须推迟你的电话。为此,您可以使用 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);
});
我正在尝试学习 RxJava,我正在转换 AsyncTask
我必须成为 Observable/Subscriber。原来的 AsyncTask
在后台加载了一张图片,然后在 onPostExecute
中将 ImageView 的可绘制对象设置为加载的图片。显示的图像在回收视图中,随着列表滚动,为列表中的每个项目加载图像。我将它转换为 Rx,但现在滚动时有很多延迟。每次在 RecyclerView 的适配器中调用 onBind
时都会调用方法 fetchThumbnail
。下面你会看到我原来的实现被注释掉了,还有新的实现。使用 RxJava 时,我没有发现内存或 cpu 使用量有显着增加。我相信我也在订阅和观察正确的线程。给出了什么?
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);
}
}
UI阻塞的原因是just(...)
运算符中的表达式是在当前线程中执行的
如果要在 subscribeOn(..)
中指定的线程中执行表达式,则必须使用 create(..)
方法创建 Observable
,而不是 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);
}
});
Observable.just
可用于已计算的值。
我假设此调用 MediaStore.Video.Thumbnails.getThumbnail(...)
处理您的图像,因此可能会滞后于您的 UI。你必须推迟你的电话。为此,您可以使用 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);
});