RecyclerView异步加载图片

RecyclerView异步加载图片

如何在不使用第三方图片加载框架的基础上实现RecyclerView和ListView的中实现异步加载图片功能?
简单的方法是我们可以使用LruCache+AsyncTask结合的方式实现。大致思路是在onBindViewHolder()方法中根据key去内存缓存中对应的bitmap,如果找到了就直接显示,如果没有找到就开启一个异步任务去下载这个bitmap,下载完成后存进内存缓存中并执行相应的回调进行展示。

1.首先是LruCache的工具类,我们可以这样写:

private static final class CacheHelper{
        private static LruCache sLruCache;
        static {
            sLruCache = new LruCache ((int)Runtime.getRuntime ().maxMemory ()/4){
                @Override
                protected int sizeOf(String key, Bitmap value) {
                    return value.getByteCount ();
                }
            };
        }
    }

2.然后是下载图片的异步任务,我们可以这样写:

private static final class ImageTask extends AsyncTask {

        private Listener mListener;

        ImageTask(Listener listener) {
            mListener = listener;
        }

        @Override
        protected Bitmap doInBackground(String... strings) {
            Bitmap bitmap = getBitmap (strings[0]);
            CacheHelper.sLruCache.put (strings[1], bitmap);
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            mListener.onSuccess (bitmap);
        }

        public interface Listener{
            void onSuccess(Bitmap bitmap);
        }

        private static Bitmap getBitmap(String url){
            Bitmap bitmap = null;
            BufferedInputStream stream = null;
            URL url1 = null;
            try {
                url1 = new URL (url);
                URLConnection connection = url1.openConnection ();
                stream = new BufferedInputStream(connection.getInputStream ());
                bitmap = BitmapFactory.decodeStream (stream);
            } catch (MalformedURLException e) {
                e.printStackTrace ();
            } catch (IOException e) {
                e.printStackTrace ();
            }finally {
                if (stream != null) {
                    try {
                        stream.close ();
                    } catch (IOException e) {
                        e.printStackTrace ();
                    }
                }
            }
            return bitmap;
        }
    }

3.在onBindViewHolder()方法中,展示图片前从缓存中拿,如果没有的话就开启一个异步任务,并指定回调。

	@Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int i) {
        Bitmap bitmap = CacheHelper.sLruCache.get ("ChatRecyclerAdapter" + i);
        if (bitmap == null) {
            new ImageTask (new ImageTask.Listener () {
                @Override
                public void onSuccess(Bitmap bitmap) {
                    viewHolder.mHead.setImageBitmap (bitmap);
                }
            }).execute (chatBean.getImageUrl (), "ChatRecyclerAdapter" + i);
        }else {
            viewHolder.mHead.setImageBitmap (bitmap);
        }
    }

这样就可以在不依赖第三方框架的情况下实现RecyclerView和ListView的中图片的异步加载。
这里只是一个简单思路,具体使用时候需要考虑RecyclerView和ListView的细节问题。比如在条目不可见时异步任务加载完毕后就不需要在回调显示了,这个可以通过让异步任务持有一个当前RecyclerView或ListView的实例,在onBindViewHolder()方法中给ImageView设置tag,然后通过这个tag找到条目的ImageView,如果为空说明已经不再屏幕中,这样我们就不需要执行显示的回调了。

你可能感兴趣的:(学习笔记,分享)