在应用开发中,经常用到ListView去加载数据,加载图片和文字是比较常见的,文字还好,图片从网络请求加载速度比较慢,所以需要把图片的加载放到另一个线程中去执行,执行完了再更新UI线程。以下列出一个我在项目中使用到的异步加载图片的解决方案,代码没有上全,给出核心部分。
大致思路是这样:
1.利用软引用来缓存图片Bitmap,用图片的URL作为缓存查找的Key;
2.设两级缓存,一级是SoftReference,二级是本地SD卡;
3.如果两级缓存都没取到图片,则从服务器获取,并加入缓存;
4.加载完后通过回调接口通知UI更新;
以下是异步加载的关键代码,其中一些工具类没有给出,自己实现就可以,比如HttpRequest是我自己写的一个类。
public class AsyncImageLoader { //Cache for image(Type String is the URL of image,the second parameter is soft reference) private HashMap<String, SoftReference<Bitmap>> imageCache = null; private Activity context; public AsyncImageLoader(Activity context){ this.context = context; imageCache = new HashMap<String, SoftReference<Bitmap>>(); } public Bitmap loadImage(final ImageView imageView,final String imageURL,final ImageCallBack imageCallBack){ //If the cache contains the reference of bitmap then return if (imageCache.containsKey(imageURL)) { SoftReference<Bitmap> bitmapReference = imageCache.get(imageURL); Bitmap bitmap = bitmapReference.get(); if (bitmap != null) { return bitmap; } } //Second cache,search local SD card else { String fileName = StringUtil.namePicture(imageURL);//获取文件名 boolean isExist = SystemUtils.findPhotoFromSDCard(Constant.INFO_PATH, fileName); if (isExist) {//是否在SD卡存在图片 Bitmap bitmap = SystemUtils.getPhotoFromSDCard(Constant.INFO_PATH, fileName); return bitmap; } } final Handler myHandler = new Handler(){ @Override public void handleMessage(Message msg) { imageCallBack.setImage(imageView, (Bitmap)msg.obj); } }; //If the bitmap not exists in cache or SD card,then get it from net new Thread(){ @Override public void run() { // TODO Auto-generated method stub boolean isNetwork = SystemUtils.checkNetwork(context); if (isNetwork) { InputStream photoStream = HttpRequest.getImageStream(imageURL);//这里是我自己写的一个类,目的是通过URL地址从服务器获取图片输入流 Bitmap bitmap; try { bitmap = ImageTools.getResizeBitmap(photoStream, 128, 128); if (bitmap != null) { String fileName = StringUtil.namePicture(imageURL); //Save image to SD card SystemUtils.savePhotoToSDCard(bitmap, fileName, Constant.INFO_PATH); //Put soft reference to cache imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap)); //Send message to update UI Message message = myHandler.obtainMessage(0, bitmap); myHandler.sendMessage(message); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }.start(); return null; } /** * Interface for load image * @author Ryan * */ public interface ImageCallBack{ //Set image for imageview through bitmap public void setImage(ImageView imageView,Bitmap bitmap); } }
Bitmap bitmap1 = asyncImageLoader.loadImage(viewHolder.imageView1, url1, new ImageCallBack() { @Override public void setImage(ImageView imageView, Bitmap bitmap) { // TODO Auto-generated method stub imageView.setImageBitmap(bitmap); } }); if (bitmap1 != null) { viewHolder.imageView1.setImageBitmap(bitmap1); }else { viewHolder.imageView1.setImageResource(R.drawable.image_bg); }
对Android&IOS感兴趣的朋友可以加入我们的讨论QQ群,在这里,我们只讨论干货:
iOS群:220223507
Android群:282552849
欢迎关注我的新浪微博和我交流:@唐韧_Ryan