Android ListView updating of Image Thumbnails using AsyncTask Causes View recycling

后端 未结 3 1637
孤独总比滥情好
孤独总比滥情好 2020-12-13 16:37

I have been trying to get thumbnails to work with an AsyncTask for image files in a ListView. I have been having the common problem of Row Recycling, and thus on scrolling t

相关标签:
3条回答
  • 2020-12-13 16:57

    From this blog post:

    What you want to do is running all per-row IO or any heavy CPU-bound routine asynchronously in a separate thread. The trick here is to do that and still comply with ListView‘s recycling behaviour. For instance, if you run an AsyncTask to load a profile picture in the adapter’s getView(), the view you’re loading the image for might be recycled for another position before the AsyncTask finishes. So, you need a mechanism to know if the view hasn’t been recycled once you’re done with the async operation.

    One simple way to achieve this is to attach some piece of information to the view that identifies which row is associated with it. Then you can check if the target row for the view is still the same when the async operation finishes. There are many ways of achieving this. Here is just a simplistic sketch of one way you could do it:

    public View getView(int position, View convertView,
            ViewGroup parent) {
        ViewHolder holder;
    
        ...
    
        holder.position = position;
    
        new ThumbnailTask(position, holder)
                .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);
    
        return convertView;
    }
    
    private static class ThumbnailTask extends AsyncTask {
        private int mPosition;
        private ViewHolder mHolder;
    
        public ThumbnailTask(int position, ViewHolder holder) {
            mPosition = position;
            mHolder = holder;
        }
    
        @Override
        protected Cursor doInBackground(Void... arg0) {
            // Download bitmap here
        }
    
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if (mHolder.position == mPosition) {
                mHolder.thumbnail.setImageBitmap(bitmap);
            }
        }
    }
    
    private static class ViewHolder {
        public ImageView thumbnail;
        public int position;
    }
    
    0 讨论(0)
  • 2020-12-13 16:57

    you can try passing in ListView into your Adapter constructor from your activity (may be even into your async task depends how you want to implement it). and compare the position using getFirstVisiblePosition() and getLastVisiblePosition() against your mPosition

    0 讨论(0)
  • 2020-12-13 17:07

    Using the AsyncTask.THREAD_POOL_EXECUTOR wil end up running multiple threads to fetch the thumnails. There is no order in the way they run or finisch and set the image for the view. When scrolling back and forth you may end up with the wrong images in your views.

    I tested the AsyncTask.THREAD_POOL_EXECUTOR and it does lead to the wrong image for some views.

    0 讨论(0)
提交回复
热议问题