ECClient 红孩子android客户端listview图片加载(优化)核心代码分析

本文分析了SyncImageLoader中的图片缓存与软引用机制。首先检查缓存中是否存在图片,若存在则直接使用;若不存在,则从网络加载并保存到缓存中,确保内存高效利用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SyncImageLoader.java中

private Map<String, SoftReference<Drawable>> imageCache = new ConcurrentHashMap<String, SoftReference<Drawable>>();
...
...
...
private void loadImage(final String mImageUrl, final Integer mt, final OnImageLoadListener mListener) {

        if (imageCache.containsKey(mImageUrl)) {
            SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
            final Drawable d = softReference.get();
            if (d != null) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mAllowLoad) {
                            mListener.onImageLoad(mt, d);
                        }
                    }
                });
                return;
            }
        }

由代码可知, 获取图片时, 是先去软引用的imageCache的map中去寻找, 获取到的Drawable d 不是空的话说明获取成功,就调用回调方法mListener.onImageLoad(mt, d); 将图片显示.
如果没有在软引用中获取到图片,则执行下面的

try {
            final Drawable d = loadImageFromUrl(mImageUrl);
            if (d != null) {
                imageCache.put(mImageUrl, new SoftReference<Drawable>(d));
            }
            handler.post(new Runnable() {
                @Override
                public void run() {
                    if (mAllowLoad) {
                        mListener.onImageLoad(mt, d);
                    }
                }
            });
        } catch (IOException e) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    mListener.onError(mt);
                }
            });
            Logger.e(TAG, e);
        }

这里是通过loadImageFromUrl(mImageUrl)的方法获取图片的Drawable的,然后调用回调方法mListener.onImageLoad(mt, d);显示图片, 如果出错, 则执行mListener.onError(mt);的回调方法.
(这里的mListener.onImageLoad(mt, d);mListener.onError(mt);都是需要我们程序员自定义编写的. 可以到调用loadImage的地方找到具体的回调方法)
看到这里, 我想, 把loadImageFromUrl(mImageUrl);的代码也拿过来就有必要了:

public static Drawable loadImageFromUrl(String url) throws IOException {
        InputStream in = null;
        OutputStream out = null;
        try {
            File f = new File(ECApplication.getCacheDirPath(), MD5.digest(url));
            if (f.exists()) {
                Logger.d(TAG, "缓存 " + f.getAbsolutePath());
                return Drawable.createFromPath(f.getAbsolutePath());
            }
            Logger.d(TAG, "网络 " + url);
            URL m = new URL(url);
            in = new BufferedInputStream((InputStream) m.getContent(), BUFFER_SIZE);
            out = new BufferedOutputStream(new FileOutputStream(f), BUFFER_SIZE);
            byte[] buffer = new byte[BUFFER_SIZE];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
        } finally {
            StreamUtil.Release(in, out);
        }
        return loadImageFromUrl(url);
    }

我们会发现它先去图片缓存的文件夹中去查找图片, 如果找不到再从网上下载, 下载完后再回调自己(return loadImageFromUrl(url);),这时候File f = new File(ECApplication.getCacheDirPath(), MD5.digest(url));已经是下载的图片了. 至此, 图片缓存中有了该图片了, 那么你可能会问了, 软引用什么时候加载的该刚下载的图片呢? 我们继续看.看到 loadImage(final String mImageUrl, final Integer mt, final OnImageLoadListener mListener)中的

try {
            final Drawable d = loadImageFromUrl(mImageUrl);
            if (d != null) {
                imageCache.put(mImageUrl, new SoftReference<Drawable>(d));
            }

对的就在这里了,通过 loadImageFromUrl(String url)得到了图片信息, 不为空的话说明成功了, 则就把该图片加入了软引用中, 供以后再次使用, 因为使用了软引用保证了内存不会出现溢出的情况.
我们再看到adapter中,如: LimitbuyAdapter.java, getView的几句代码:

Drawable d = drawables[position];
        if (d == null) {
            view.setTag(position);
            loadImage(position, list.get(position).getPic());
        } else {
            holderView.goodsIconIv.setBackgroundDrawable(d);
        }

当图片资源并未获取到或者在获取的过程中,图片的位置会因为还没有得到图片而不显示内容. 这里没有让imageview加载一个默认的图片以提高用户体验. 我们可以根据需要在这里加上在图片未获取到时显示一张我们的默认图片的代码.

看完这些, 您可能会问final OnImageLoadListener mListener 是在哪里定义的呢? 我们看到ImageAsyncLoaderAdpter.java:

SyncImageLoader.OnImageLoadListener imageLoadListener = new SyncImageLoader.OnImageLoadListener() {

        @Override
        public void onImageLoad(Integer position, Drawable drawable) {
            onImageLoadFinish(position, drawable);
        }

        @Override
        public void onError(Integer t) {
            onImageLoadError(t);
        }

    };

没错就是这里, 具体怎么实现的,可以到onImageLoadFinish(position, drawable);和onImageLoadError(t);的定义中去看了,这两个方法其实是我们自定义的,前面也有提到过.
好了. 先分析到这了.

总结:
本篇主要分析了代码中对图片做缓存和软引用的过程. 这样对图片的处理也是对涉及到图片listview的优化的很重要的一部分.
希望对大家有帮助. 谢谢.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值