Reputation: 83
Hi i have my adapter for RecyclerView and i need to show a large list (different lists with images). All images i am loading into ImageView from a separate thread. Each thread for each ImageView. The problem is in that when i am changing data for my adapter and calling notifyDataSetChanged(); - sometimes the new ImageViews are displaying images from a previous data set. I understand that this is happening because of RecyclerView is reusing the ViewHolder item - in which the old thread is still downloading the old image, not new. So i am wondering how can i stop all threads when my dataset in adapter is changing. May be the approach is to put all threads into an array and stop all of them before calling notifyDataSetChanged();? But i think there are can be more elegant solutions? This is my code:
@Override
public void onBindViewHolder(ItemHolder holder, int position) {
........
holder.itemIcon.setImageResource(tree.getDefaultCover());
BitmapWorkerTask bitmapWorkerTask = new BitmapWorkerTask(holder.itemIcon, tree);
bitmapWorkerTask.execute(file);
......
}
then in my Worker task i am setting Bitmap in postExecute method
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
mIconView.setImageBitmap(result);
}
Upvotes: 0
Views: 375
Reputation: 1994
Android Dev site has addressed the exact problem for working with images in a list UI. Basically the idea is to define a wrapper over the drawable which keeps a reference to the task which is supposed to load the image for it. Since views are recycled in a list UI, a particular view might get recycled even before the task to load the image for it could be executed. This pattern helps to preempt this and cancel the task.
https://developer.android.com/training/displaying-bitmaps/process-bitmap.html#concurrency
Upvotes: 1
Reputation: 14755
With AsycTask.execute
only one task/thread is actve at a time. the next is started when the previous finishes. in your task you have to check isCanceled()
at least in the beginning of doInBackground
and in the beginning of onPostExecute
.
If holder knows taks and task knows holder you can ask each holder to stop it-s task (call the cancle method).
since you have a cyclic reference between holder and task there is a risk for memory leaks.
you must make shure that the holder forgets it-s task once it is cancleded/finished or there is a configuration change (i.e. screen rotation).
I have done this in APhotoManager. It contains a GalleryCursorFragment with the gridview and a GalleryCursorFragment with an embedded GridCellViewHolder
Upvotes: 1
Reputation: 798
you can stop do in asyncktack to get new image in recycler view use this code for stoping asncktack if (asyncktask != null){ asyncktask .cancel(true);} then call notifyDataSetChanged();
Upvotes: 0
Reputation: 2256
No need to reinvent a wheel here. Just use Glide.
Glide.with(this).load("img_url").into(imageView);
Done.
Upvotes: 0