一个在ListView上异步双缓存获取图片的实现

这个在Listview 上异步刷新缓存图片弄了一天还没搞定,我原先的想法是在getview里开一个new Thread来获取缩略图,但是引起的问题是只会在listview的最后一行进行图片刷新。于是在网上找了下资料,也尝试了很多,终于在看到这篇文章时让我眼前一亮,最后试验成功。

参考的文章地址:http://blog.csdn.net/onerain88/article/details/7008409

先看截图


上面的qq.jpg和yu.jpg就是效果的实现,因为美工还没有发过来合适的图片。所以有些图片看上去很难看。。。

下面是主要的实现代码。

首先是一个处理网络图片的类AsyncBitmapLoader,这个类有两个缓存,如果两个缓存都没有找到,才去网络下载

[java]  view plain copy
  1. package cn.jtang.netdisk.utils;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.lang.ref.SoftReference;  
  8. import java.util.HashMap;  
  9. import java.util.Map;  
  10.   
  11. import android.graphics.Bitmap;  
  12. import android.graphics.BitmapFactory;  
  13. import android.os.Handler;  
  14. import android.os.Message;  
  15. import android.widget.ImageView;  
  16. import cn.jtang.netdisk.mode.NotLoginException;  
  17.   
  18. public class AsyncBitmapLoader {  
  19.     //Map<String, String> filemap=new HashMap<String, String>();  
  20.     /** 
  21.      * 内存图片软引用缓冲 
  22.      */  
  23.     private HashMap<String, SoftReference<Bitmap>> imageCache = null;  
  24.   
  25.     public AsyncBitmapLoader() {  
  26.         imageCache = new HashMap<String, SoftReference<Bitmap>>();  
  27.     }  
  28.   
  29.     public Bitmap loadBitmap(final ImageView imageView, final String fileNameURL,  
  30.             final ImageCallBack imageCallBack) {  
  31.         // 在内存缓存中,则返回Bitmap对象  
  32.         if (imageCache.containsKey(fileNameURL)) {  
  33.             SoftReference<Bitmap> reference = imageCache.get(fileNameURL);  
  34.             Bitmap bitmap = reference.get();  
  35.             if (bitmap != null) {  
  36.                 return bitmap;  
  37.             }  
  38.         } else {  
  39.             /** 
  40.              * 加上一个对本地缓存的查找 
  41.              */  
  42.             String bitmapName = fileNameURL  
  43.                     .substring(fileNameURL.lastIndexOf("/") + 1);  
  44.             File cacheDir = new File("/mnt/sdcard/");  
  45.             File[] cacheFiles = cacheDir.listFiles();  
  46.             int i = 0;  
  47.             for (; i < cacheFiles.length; i++) {  
  48.                 if (bitmapName.equals(cacheFiles[i].getName())) {  
  49.                     break;  
  50.                 }  
  51.             }  
  52.   
  53.             if (i < cacheFiles.length) {  
  54.                 return BitmapFactory.decodeFile("/mnt/sdcard/"  
  55.                         + bitmapName);  
  56.             }  
  57.         }  
  58.   
  59.         final Handler handler = new Handler() {  
  60.             /* 
  61.              * (non-Javadoc) 
  62.              *  
  63.              * @see android.os.Handler#handleMessage(android.os.Message) 
  64.              */  
  65.             @Override  
  66.             public void handleMessage(Message msg) {  
  67.                 // TODO Auto-generated method stub  
  68.                 imageCallBack.imageLoad(imageView, (Bitmap) msg.obj);  
  69.             }  
  70.         };  
  71.   
  72.         // 如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片  
  73.         new Thread() {  
  74.             /* 
  75.              * (non-Javadoc) 
  76.              *  
  77.              * @see java.lang.Thread#run() 
  78.              */  
  79.             @Override  
  80.             public void run() {  
  81.                 // TODO Auto-generated method stub  
  82.                 //InputStream bitmapIs = HttpUtils.getStreamFromURL(imageURL);  
  83.                 HttpCookieUtils httpCookieUtils=new HttpCookieUtils();  
  84.                 String imgName = null;  
  85.                 try {  
  86.                     imgName = httpCookieUtils.preview(fileNameURL, "40""40");  
  87.                 } catch (NotLoginException e1) {  
  88.                     // TODO Auto-generated catch block  
  89.                     e1.printStackTrace();  
  90.                 } catch (IOException e1) {  
  91.                     // TODO Auto-generated catch block  
  92.                     e1.printStackTrace();  
  93.                 }  
[java]  view plain copy
  1.                                  //这里是我根据我自己的需求,改变的,如果你有自己的需求,都在下面进行处理  
  2.                 Bitmap bitmap=BitmapUtils.getHttpBitmap(Constants.API_HOST+Constants.API_SHOW+imgName);  
  3.                 imageCache.put(fileNameURL, new SoftReference<Bitmap>(bitmap));  
  4.                 Message msg = handler.obtainMessage(0, bitmap);  
  5.                 handler.sendMessage(msg);  
  6.   
  7.                 File dir = new File("/mnt/sdcard/");  
  8.                 if (!dir.exists()) {  
  9.                     dir.mkdirs();  
  10.                 }  
  11.   
  12.                 File bitmapFile = new File("/mnt/sdcard/"  
  13.                         + fileNameURL.substring(fileNameURL.lastIndexOf("/") + 1));  
  14.                 if (!bitmapFile.exists()) {  
  15.                     try {  
  16.                         bitmapFile.createNewFile();  
  17.                     } catch (IOException e) {  
  18.                         // TODO Auto-generated catch block  
  19.                         e.printStackTrace();  
  20.                     }  
  21.                 }  
  22.                 FileOutputStream fos;  
  23.                 try {  
  24.                     fos = new FileOutputStream(bitmapFile);  
  25.                     bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);  
  26.                     fos.close();  
  27.                 } catch (FileNotFoundException e) {  
  28.                     // TODO Auto-generated catch block  
  29.                     e.printStackTrace();  
  30.                 } catch (IOException e) {  
  31.                     // TODO Auto-generated catch block  
  32.                     e.printStackTrace();  
  33.                 }  
  34.             }  
  35.         }.start();  
  36.   
  37.         return null;  
  38.     }  
  39.   
  40.     /** 
  41.      * 回调接口 
  42.      *  
  43.      * @author onerain 
  44.      *  
  45.      */  
  46.     public interface ImageCallBack {  
  47.         public void imageLoad(ImageView imageView, Bitmap bitmap);  
  48.     }  
  49. }  
PS:我这里用到了两个缓冲,一是内存缓存,一个是本地缓存(即SD卡缓存),其中用到了SoftReference,这个类的主要作用是生成一个“软引用”,你可以认为是一种随时会由于JVM垃圾回收机制回收掉的Map对象(而平时我们所用到的引用不释放的话不会被JVM回收),之所以用到软引用,就是考虑到android对图片的缓存是有大小限制的,当超过这个大小时,就一定要释放,如果你用引用,保持不释放的话,那么FC(Force close)就离你不远了。。。我这里还用到了一个本地缓存的机制,是和参考博客不太一样的地方,只是提供一种思路,方法还没有完善(主要因为和服务器还没约定好关于图片的命名规则),主要作用是在用户浏览过大量图片之后(超过内存缓存容量之后),保留在本地,一是为了提高读取速度,二是可以减少流量消耗!

接下来就是适配器,我创建了FileListAdapter

[java]  view plain copy
  1. public class FileListAdapter extends BaseAdapter {  
  2.     private Context context; // 运行上下文  
  3.     private List<Files> groupList = new ArrayList<Files>(); // 所有文件及文件夹  
  4.     // private List<List<String>> childList = new  
  5.     // ArrayList<List<String>>();//文件集合  
  6.     private LayoutInflater listContainer; // 视图容器  
  7.     private Files files;  
  8.     private boolean isOk;  
  9.     private boolean isFirst = true;  
  10.     private Handler handler;  
  11.     private ViewHolder holder;  
  12.     private AsyncBitmapLoader asyncLoader = null;  
  13.   
  14.     //原来每个控件都设置为static。导致在绘画和重命名时出现错位,删除就ok了  
  15.     static class ViewHolder {  
  16.          Button downButton;  
  17.          Button friendButton;  
  18.          Button shareButton;  
  19.          Button renameButton;  
  20.          Button deleteButton;  
  21.          Button select_img;  
  22.          ImageView img_isView, imgfile;  
  23.          TextView fileName, fileDate;  
  24.     }  
  25.   
  26.     public FileListAdapter(Context context, List<Files> groups) {  
  27.         this.context = context;  
  28.         this.groupList = groups;  
  29.         listContainer = LayoutInflater.from(context);  
  30.         this.asyncLoader = new AsyncBitmapLoader();  
  31.           
  32.   
  33.     }  
  34.   
  35.     @Override  
  36.     public int getCount() {  
  37.         // TODO Auto-generated method stub  
  38.         return groupList.size();  
  39.     }  
  40.   
  41.     @Override  
  42.     public Object getItem(int position) {  
  43.         // TODO Auto-generated method stub  
  44.         return groupList.get(position);  
  45.     }  
  46.   
  47.     @Override  
  48.     public long getItemId(int position) {  
  49.         // TODO Auto-generated method stub  
  50.         return position;  
  51.     }  
  52.   
  53.     @Override  
  54.     public View getView(int position, View convertView, ViewGroup parent) {  
  55.         // TODO Auto-generated method stub  
  56.   
  57.         if (convertView == null) {  
  58.             convertView = listContainer.inflate(R.layout.item_filelist, null);  
  59.             holder = new ViewHolder();  
  60.             // 初始化绑定控件  
  61.             holder.imgfile = (ImageView) convertView  
  62.                     .findViewById(R.id.img_fileimg);  
  63.             holder.deleteButton = (Button) convertView  
  64.                     .findViewById(R.id.btn_delete);  
  65.             holder.downButton = (Button) convertView  
  66.                     .findViewById(R.id.btn_download);  
  67.             holder.friendButton = (Button) convertView  
  68.                     .findViewById(R.id.btn_friend);  
  69.             holder.renameButton = (Button) convertView  
  70.                     .findViewById(R.id.btn_rename);  
  71.             holder.shareButton = (Button) convertView  
  72.                     .findViewById(R.id.btn_share);  
  73.             holder.fileName = (TextView) convertView  
  74.                     .findViewById(R.id.txt_fileName);  
  75.             holder.fileDate = (TextView) convertView  
  76.                     .findViewById(R.id.txt_fileDate);  
  77.             holder.select_img = (Button) convertView  
  78.                     .findViewById(R.id.btn_select);  
  79.             holder.img_isView = (ImageView) convertView  
  80.                     .findViewById(R.id.img_checkimg);  
  81.         } else {  
  82.             holder = (ViewHolder) convertView.getTag();  
  83.         }  
  84.   
  85.         // 进行初始化赋值  
  86.         initData(convertView, position);  
  87.   
  88.         return convertView;  
  89.     }  
  90.   
  91.     private void initData(View convertView, final int position) {  
  92.         // TODO Auto-generated method stub  
  93.         Files files = new Files();  
  94.         files = groupList.get(position);  
  95.         holder.fileName.setText(files.getFileName());  
  96.   
  97.         // 初始化为未展开  
  98.         if (convertView.getMeasuredHeight() == 95  
  99.                 || convertView.getMeasuredHeight() == 96) {  
  100.             ViewGroup.LayoutParams params = convertView.getLayoutParams();  
  101.             params.height = convertView.getMeasuredHeight() - 40;  
  102.             convertView.setLayoutParams(params);  
  103.         }  
  104.   
  105.         // 判断是文件  
  106.         if (files.isFile()) {  
  107.             String fileType = files.getFileName().substring(  
  108.                     files.getFileName().lastIndexOf("."),  
  109.                     files.getFileName().length());  
  110.             holder.fileDate.setText(files.getLastModified() + " "  
  111.                     + files.getLength());  
  112.             holder.downButton.setText("下载");  
  113.             holder.downButton.setTag("下载");  
  114.             System.out.println("fileType" + fileType);  
  115.             if (fileType.equals(".jpg") || fileType.equals(".png")  
  116.                     || fileType.equals(".gif") || fileType.equals(".Jpeg")  
  117.                     || fileType.equals(".bmp")) {  
  118.                 holder.imgfile.setImageBitmap(null);  
  119.                 // 根据图片URL去查找内存缓存有没有对应的Bitmap对象,并传递回调方法,如果没有,则等下载完毕回调  
  120.                 Bitmap bitmap = asyncLoader.loadBitmap(holder.imgfile,  
  121.                         groupList.get(position).getPath(), new ImageCallBack() {  
  122.                             @Override  
  123.                             public void imageLoad(ImageView imageView,  
  124.                                     Bitmap bitmap) {  
  125.                                 // TODO Auto-generated method stub  
  126.                                 imageView.setImageBitmap(bitmap);  
  127.                             }  
  128.                         });  
  129.   
  130.                 if (bitmap == null) {  
  131.                     holder.imgfile.setImageResource(R.drawable.ic_launcher);  
  132.                 } else {  
  133.                     holder.imgfile.setImageBitmap(bitmap);  
  134.                 }  
  135.   
  136.             }  
  137.   
  138.         } else {  
  139.             holder.fileDate.setText(files.getLastModified());  
  140.             holder.downButton.setText("打开");  
  141.             holder.downButton.setTag("打开");  
  142.             groupList.get(position).setFileImg("file");  
  143.             holder.imgfile.setBackgroundResource(R.drawable.img_filelist);  
  144.         }  
  145.     }  
  146. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值