Android开源中国客户端学习 异步加载图片

这次的内容又是很简单 异步加载图片大家可能做的也很多了 通过阅读osc的源码 也算是 学习人家的一种架构吧,好歹作者的经验也比我丰富。

其实osc的图片异步加载也是使用了两级结构,即 内存缓存和sd卡缓存。整体思路:显示图片时先从内存缓存中找,如果找到,就直接返回这个bitmap并显示,如果找不到从sd卡找,找到就显示,找不到就从网路获取并保存到内存缓存和sd卡中

时序图如下
图片说明文字

1.在Adapter等地方设置这个显示这个图片,其实是调用了BitmapManager的loadBitmap函数

1
bmpManager.loadBitmap(imgSmall, listItemView.image, BitmapFactory.decodeResource(context.getResources(), R.drawable.image_loading));

2.loadBitmap函数代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp, int width, int height) {  
        imageViews.put(imageView, url);  
        Bitmap bitmap = getBitmapFromCache(url);  

        if (bitmap != null) {  
            //显示缓存图片
            imageView.setImageBitmap(bitmap);  
        } else {  
            //加载SD卡中的图片缓存
            String filename = FileUtils.getFileName(url);
            String filepath = imageView.getContext().getFilesDir() + File.separator + filename;
            File file = new File(filepath);
            if(file.exists()){
                //显示SD卡中的图片缓存
                Bitmap bmp = ImageUtils.getBitmap(imageView.getContext(), filename);
                imageView.setImageBitmap(bmp);
            }else{
                //线程加载网络图片
                imageView.setImageBitmap(defaultBmp);
                queueJob(url, imageView, width, height);
            }
        }  
    }  

这里先分析从内存Cache中获取Bitmap的实现:

在分析获取缓存之前有个imageViews成员变量需要解释一下

1
 imageViews.put(imageView, url);  

这个 imageViews.put(imageView, url); 的定义是

1
2
3
Map<ImageView, String>

 imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());

这里的Collections.synchronizedMap 是为了让HashMap可以用于多线程的环境

而 WeakHashMap当某个键不再正常使用时,将自动移除其条目。这个imageViews是为了在线程池中把imageview和url(其实就是从网络取回来的bitmap)一一对应 稍后还会看到。

4.getBitmpaFromCache函数

1
2
3
4
5
6
7
   public Bitmap getBitmapFromCache(String url) {  
        Bitmap bitmap = null;
        if (cache.containsKey(url)) {  
            bitmap = cache.get(url).get();  
        }  
        return bitmap;  
    }  

那么,这个Cache是个什么东西呢?

1
2
 private static HashMap<String, SoftReference<Bitmap>> cache;  
 cache = new HashMap<String, SoftReference<Bitmap>>();  

原来是一个HashMap 其中他的键值String是那个需要显示的Bitmap的url 我以前做的项目是把这个url md5了 市面上很多应用比如京东也是进行的md5再放入缓存

至于SofrReference请自行google。

继续看代码,。如果从缓存中取到了bitmap,就直接显示,若没有就执行

1
    Bitmap bmp = ImageUtils.getBitmap(imageView.getContext(), filename);

从sd卡取,如果sd卡没有这个文件,那直接从网路下载了 在此之前 还让imageview显示了一个默认图片

7.queueJob()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 public void queueJob(final String url, final ImageView imageView, final int width, final int height) {  
        /* Create handler in UI thread. */  
        final Handler handler = new Handler() {  
            public void handleMessage(Message msg) {  
                String tag = imageViews.get(imageView);  
                if (tag != null && tag.equals(url)) {  
                    if (msg.obj != null) {  
                        imageView.setImageBitmap((Bitmap) msg.obj);  
                        try {
                            //向SD卡中写入图片缓存
                            ImageUtils.saveImage(imageView.getContext(), FileUtils.getFileName(url), (Bitmap) msg.obj);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } 
                }  
            }  
        };  

        pool.execute(new Runnable() {   
            public void run() {  
                Message message = Message.obtain();  
                message.obj = downloadBitmap(url, width, height);  
                handler.sendMessage(message);  
            }  
        });  
    } 

这里又是一个handler+thread了

有同学会说,这里木有thread,其实那个post就是一个线程池了

看定义

1
2
  private static ExecutorService pool;  
 pool = Executors.newFixedThreadPool(5);  //固定线程池

就是把downloadBitmap的任务放到线程池中执行了,等执行完了就发消息给handler

handler会使用从imageviews中保存的url进行匹配,如果消息写到的url是imageview需要显示的那个,就显示到imageview上

注意在从网路download取回bitmap之后会把bitmap放到cache'中 这句话在downloadBitmap()函数中

cache.put(url, new SoftReference(bitmap));
13.最后异步就是把获取到的bitmap保存到sd卡了

1
2
ImageUtils.saveImage(imageView.getContext(), FileUtils.getFileName(url), (Bitmap) msg.obj);
//向SD卡中写入图片缓存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值