打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android ListView图片异步加载显示
001package cn.jd3g.utils;
002  
003import java.lang.ref.SoftReference;
004import java.util.HashMap;
005import java.util.LinkedHashMap;
006import java.util.Map.Entry;
007  
008import android.graphics.Bitmap;
009import android.os.Handler;
010import android.util.Log;
011import android.widget.ImageView;
012  
013/**
014 * 利用多线程异步加载图片并更新视图
015 
016 * @author xfzhang
017 
018 */
019public final class AsynImageLoader {
020  
021    private LoaderThread thread;// 加载图片并发消息通知更新界面的线程
022    private HashMap<String, SoftReference<Bitmap>> imageCache;// 图片对象缓存,key:图片的url
023    private Handler handler;// 界面Activity的Handler对象
024  
025    public AsynImageLoader(Handler handler) {
026        imageCache = new HashMap<String, SoftReference<Bitmap>>();
027        this.handler = handler;
028    }
029  
030    /**
031     * 加载图片前显示到指定的ImageView中,图片的url保存在视图对象的Tag中
032     
033     * @param imageView
034     *            要显示图片的视图
035     * @param defaultBitmap
036     *            加载需要显示的提示正在加载的默认图片对象
037     */
038    public void loadBitmap(ImageView imageView, Bitmap defaultBitmap) {
039        // 图片所对应的url,这个值在加载图片过程中很可能会被改变
040        String url = (String) imageView.getTag();
041        if (imageCache.containsKey(url)) {// 判断缓存中是否有
042            SoftReference<Bitmap> softReference = imageCache.get(url);
043            Bitmap bitmap = softReference.get();
044            if (bitmap != null) {// 如果图片对象不为空,则可挂接更新视图,并返回
045                imageView.setImageBitmap(bitmap);
046                return;
047            } else {// 如果为空,需要将其从缓存中删除(其bitmap对象已被回收释放,需要重新加载)
048                Log.e("TAG", "cache bitmap is null");
049                imageCache.remove(url);
050            }
051        }
052        imageView.setImageBitmap(defaultBitmap);// 先显示一个提示正在加载的图片
053        if (thread == null) {// 加载线程不存在,线程还未启动,需要新建线程并启动
054            thread = new LoaderThread(imageView, url);
055            thread.start();
056        } else {// 如果存在,就调用线程对象去加载
057            thread.load(imageView, url);
058        }
059  
060    }
061  
062    /**
063     * 释放缓存中所有的Bitmap对象,并将缓存清空
064     */
065    public void releaseBitmapCache() {
066        if (imageCache != null) {
067            for (Entry<String, SoftReference<Bitmap>> entry : imageCache.entrySet()) {
068                Bitmap bitmap = entry.getValue().get();
069                if (bitmap != null) {
070                    bitmap.recycle();// 释放bitmap对象
071                }
072            }
073            imageCache.clear();
074        }
075    }
076  
077    /**
078     * 加载图片并显示的线程
079     */
080    private class LoaderThread extends Thread {
081  
082        LinkedHashMap<String, ImageView> mTaskMap;// 需要加载图片并显示的图片视图对象任务链
083        private boolean mIsWait;// 标识是线程是否处于等待状态
084  
085        public LoaderThread(ImageView imageView, String url) {
086            mTaskMap = new LinkedHashMap<String, ImageView>();
087            mTaskMap.put(url, imageView);
088        }
089  
090        /**
091         * 处理某个视图的更新显示
092         
093         * @param imageView
094         */
095        public void load(ImageView imageView, String url) {
096            mTaskMap.remove(imageView);// 任务链中可能有,得先删除
097            mTaskMap.put(url, imageView);// 将其添加到任务中
098            if (mIsWait) {// 如果线程此时处于等待得唤醒线程去处理任务队列中待处理的任务
099                synchronized (this) {// 调用对象的notify()时必须同步
100                    this.notify();
101                }
102            }
103        }
104  
105        @Override
106        public void run() {
107            while (mTaskMap.size() > 0) {// 当队列中有数据时线程就要一直运行,一旦进入就要保证其不会跳出循环
108                mIsWait = false;
109                final String url  = mTaskMap.keySet().iterator().next();
110                final ImageView imageView = mTaskMap.remove(url);
111                if (imageView.getTag() == url) {// 判断视图有没有复用(一旦ImageView被复用,其tag值就会修改变)
112                    final Bitmap bitmap = MyConnection.getBitmapByUrl(url);// 此方法应该是从网络或sd卡中加载
113                    try {
114                        Thread.sleep(1000);// 模拟网络加载数据时间
115                    } catch (InterruptedException e1) {
116                        e1.printStackTrace();
117                    }
118                    // 将加载的图片放入缓存map中
119                    imageCache.put(url, new SoftReference<Bitmap>(bitmap));
120                    if (url == imageView.getTag()) {// 再次判断视图有没有复用
121                        handler.post(new Runnable() {// 通过消息机制在主线程中更新UI
122                            @Override
123                            public void run() {
124                                imageView.setImageBitmap(bitmap);
125                            }
126                        });
127                    }
128                }
129                if (mTaskMap.isEmpty()) {// 当任务队列中没有待处理的任务时,线程进入等待状态
130                    try {
131                        mIsWait = true;// 标识线程的状态,必须在wait()方法之前
132                        synchronized (this) {
133                            this.wait();// 保用线程进入等待状态,直到有新的任务被加入时通知唤醒
134                        }
135                    } catch (InterruptedException e) {
136                        e.printStackTrace();
137                    }
138                }
139            }
140        }
141    }
142}
01private class ProductListAdapter extends BaseAdapter {
02  
03        private AsynImageLoader mImageAsynLoader;
04  
05        public ProductListAdapter() {
06            mImageAsynLoader = new AsynImageLoader(mHandler);
07        }
08  
09        @Override
10        public int getCount() {
11            int size = Math.min(mLastItemViewIndex + 1, mDataList.size());
12            mLastItemViewIndex = size - 1;
13            return size;
14        }
15  
16        @Override
17        public Object getItem(int position) {
18            return mDataList.get(position);
19        }
20  
21        @Override
22        public long getItemId(int position) {
23            return position;
24        }
25  
26        @Override
27        public View getView(int position, View convertView, ViewGroup parent) {
28            if (convertView == null) {
29                convertView = getLayoutInflater().inflate(R.layout.product_list_item,
30                        null);
31            }
32            ImageView imageView = (ImageView) convertView
33                    .findViewById(R.id.iv_item_product_image);
34            Map<String, String> map = mDataList.get(position);
35//存放图片所对应的url
36            imageView.setTag(map.get("product_pic_address"));
37            mImageAsynLoader.loadBitmap(imageView, mDefautBitmap);
38            return convertView;
39        }
40    }
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
网络通信框架Volley使用详细说明
Android利用Volley异步加载数据(JSON和图片)完整示例
使用ImageLoader实现图片异步加载
高效使用Bitmaps(三) 神奇的Cache
Android面试-App性能优化
Android Universal Image Loader
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服