Android ListView网络加载图片之内存缓存

之前学习过关于图片缓存的,但是总感觉不是很好,现在看了慕课网视频后,觉得虽然只是一小步的优化,但是先记录于此,以便后续继续学习。
如果没有使用图片缓存,我们每次滑动listView都会重新加载图像数据,这样不仅耗费用户的流量,而且用户体验感也不好,因此必须使用缓存,本次先学习的是内存的缓存。关于缓存图片的方法很多,我比较钟情于LruCache(),LruCache以键值对的形式,初始化时,需要设置缓存的大小K,超过这个大小的数据将会被清除(清除的数据,是那些被先加入的数据,而且最近没有使用到的数据)。LruCache内部的数据结构是LinkedHashMap存储的。使用LruCache方法非常简单,只要几步即可:
1. 定义LruCache键值对对象分别是URL和对应的图片;
2.设置Lrucache缓存的大小,重写sizeOf的方法,返回的是图片大小;
3.定义将Bitnap对象存入缓存中方法;
4.定义根据url取出缓存Bitmap对象

下面我们来逐步实现:
1. 定义LruCache键值对对象分别是URL和对应的图片

private LruCache<String, Bitmap> mCaches;

2.设置Lrucache缓存的大小,重写sizeOf的方法,返回的是图片大小

public ImageLoaders() {
        //获取最大可用内存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheSize = maxMemory / 4;
        mCaches = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                //每次存入缓存时使用
                return bitmap.getByteCount();
            }
        };
    }

3.定义将Bitnap对象存入缓存中方法

/**
     * 将Bitnap对象存入缓存中
     *
     * @param url    //缓存图片的路径
     * @param bitmap //缓存图片的对象
     */
    public void addBitmapToCache(String url, Bitmap bitmap) {
        if (getBitmapForCache(url) == null&&bitmap !=null) {
            mCaches.put(url, bitmap);
        }
    }

4.定义根据url取出缓存Bitmap对象

/**
     * 通过URL获取缓存图片,返回Bitmap对象或者返回null值
     *
     * @param url
     * @return
     */
    public Bitmap getBitmapForCache(String url) {
        return mCaches.get(url);//底层linkHasMap
    }
至此,LruCache初始话完成了,下面要做的就是如何操作了。
首先定义一个方法给adapter调用,在adapter只要调用这个方法就好。
/**
     * 通过ImageView和url显示图片方法
     *
     * @param imageView
     * @param url
     *
     * 调用方法:
     * (1)在自定义的adapter中设置一个标记imageView.setTag(url)(注:在显示图片是先拿标记中的url和获取图片的url对比,一致时再显示图片)
     * (2)调用new ImageLoader().showImageViewByAsyncTask(imageView,url);
     */
    public void showImageViewByAsyncTask(ImageView imageView, String url) {
        //先从缓存中获取图片
        Bitmap bitmap = getBitmapForCache(url);

        if (bitmap == null) {//不存在缓存中,直接开启异步任务下载
            new MyAsnyTask(imageView, url).execute(url);
        } else {//存在缓存中,直接显示
            imageView.setImageBitmap(bitmap);
        }
    }

上面当图片不存在缓存中时,我们开启一个异步线程去下载,那么接下来我们就实现MyAsnyTask。

 class MyAsnyTask extends AsyncTask<String, Void, Bitmap> {
        private ImageView imageView;
        private String url;

        public MyAsnyTask(ImageView imageView, String url) {
            this.imageView = imageView;
            this.url = url;
        }

        @Override
        protected Bitmap doInBackground(String... strings) {
            String urlStr = strings[0];
            Bitmap bitmap = getBitmapForUrl(urlStr);

            //将不在缓存的图片加入缓存
            addBitmapToCache(urlStr, bitmap);
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            //在向主线程提交时先检查Tag避免图片错位
            if (imageView.getTag().equals(url))
                imageView.setImageBitmap(bitmap);
        }
    }

看,是不是基本完成了呢?我们还要实现异步任务中的getBitmapForUrl(urlStr)方法就好,当然在这个方法中我们还可以做很多工作,如对图片的压缩加工等,在这里,我们以最简单的方法实现即可。

 /**
     * 通过url用get方法获取Bitmap对象图片
     *
     * @param url
     * @return
     */
    public Bitmap getBitmapForUrl(String url) {
        try {
            URL u = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) u.openConnection();
            BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
            Bitmap bitmap = BitmapFactory.decodeStream(bis);
            bis.close();
            conn.disconnect();
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

以上就是一个简单的工具类了,使用也比较简单,只需在自定义的adapter中:

imageView.setTag(url);
new ImageLoader().showImageViewByAsyncTask(imageView,url);
//不建议每次使用都new一次,最好在构造器中进行实例化

这是一个非常简单的例子,个人知识有限,也只能写出这样了,如果有写得不好的地方,欢迎指出!不喜勿喷,谢谢大家!

源码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值