android实现异步加载图片类
其中牵涉到的关键知识点
1,回调机制,不过回调接口的实现方式有多种多样,可以是一个类继承该接口,也可以是作为一个方法参数;
可以参照自己的这篇博客:
http://www.cnblogs.com/bobodeboke/archive/2013/04/24/3040662.html
2,hashmap联通softReference实现缓存机制。
3,注意这种回调的处理,首先图片是用的默认图片(这里是应用图标进行占位),当回调接口调用时候,替换为网络获得的图片。
详见代码:
package com.bobo.myimageloader.util; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.ref.SoftReference; import java.net.URL; import java.util.Date; import java.text.SimpleDateFormat; import java.util.HashMap; import android.R; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.Log; import android.widget.ImageView; //异步加载工具类 public class AsycImageLoader { private Context mContext; // 用来缓存图片信息 private HashMap<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>(); private Bitmap defbitmap; private String LOG_TAG = "AsycImageLoader"; // 异步加载图片工具类,如果异步加载不成功就返回图标文件 public AsycImageLoader(Context context) { this.mContext = context; // 默认的图片 this.defbitmap = BitmapFactory.decodeResource(mContext.getResources(), com.bobo.myimageloader.R.drawable.ic_launcher); } /** * 从sd卡中异步加载图片 * * @param uri图片所在的文件路径 * @param imageView显示图片的imageview * @param imageCallBack图片的回调接口 * @return */ private Bitmap loadBitmapFormSD(final String uri, final ImageView imageView, final ImageCallBack imageCallBack, final int optsize) { if (this.imageCache.containsKey(uri)) { SoftReference<Bitmap> softReference = this.imageCache.get(uri); Bitmap bitmap = softReference.get(); if (bitmap != null) { return bitmap; } } final Handler handler = new Handler() { public void handleMessage(Message msg) { // 调用回调接口 imageCallBack.imageLoaded((Bitmap) msg.obj, imageView); } }; // 从文件路径总加载相对费时,因此开启线程进行操作 new Thread() { public void run() { Bitmap bitmap = null; if ((new File(uri)).isFile()) { // 说明对应路径有错 bitmap = BitmapFactory.decodeResource( mContext.getResources(), com.bobo.myimageloader.R.drawable.ic_launcher); } bitmap = getBitmapFromFile(uri, optsize); imageCache.put(uri, new SoftReference<Bitmap>(bitmap)); /* * Message msg=new Message(); msg.obj=bitmap; */ Message msg = handler.obtainMessage(0, bitmap); handler.sendMessage(msg); } }.start(); return defbitmap; } /** * 从文件路径中获取文件可以设定opt参数 * * @param uri * @return */ private Bitmap getBitmapFromFile(String uri, int opsize) { System.out.println("取出文件的路径是:"+uri); BitmapFactory.Options opt = new BitmapFactory.Options(); // 设置缩放比例,如果设置为2,则图像会是原来的1/2 opt.inSampleSize = opsize; opt.inPurgeable = true; Bitmap bitmap = BitmapFactory.decodeFile(uri, opt); if (bitmap != null) { return bitmap; } return this.defbitmap; } private Bitmap loadBitmapFromNet(final String uri, final ImageView imageView, final ImageCallBack imageCallBack, final int optsize) { if (imageCache.containsKey(uri)) { SoftReference<Bitmap> soft = imageCache.get(uri); Bitmap bitmap = soft.get(); return bitmap; } // 如果没有需要开启线程进行下载 final Handler handler = new Handler() { public void handleMessage(Message msg) { imageCallBack.imageLoaded((Bitmap) msg.obj, imageView); } }; new Thread() { public void run() { Bitmap bitmap = null; try { String savePath = getFileSavePath(); downLoadImageFormNet(uri, savePath); bitmap = getBitmapFromFile(savePath, optsize); imageCache.put(uri, new SoftReference<Bitmap>(bitmap)); Message msg=handler.obtainMessage(0, bitmap); handler.sendMessage(msg); } catch (Exception e) { Log.d(LOG_TAG, "从网络下载保存bitmap失败"); bitmap = BitmapFactory.decodeResource( mContext.getResources(), com.bobo.myimageloader.R.drawable.ic_launcher); } } }.start(); return defbitmap; } // 从网络下载并且保存图片资源 protected void downLoadImageFormNet(String uri, String savePath) { // 如果下载的就是不做处理的原始文件 Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeStream((new URL(uri)).openStream()); FileOutputStream fos = new FileOutputStream(savePath); bitmap.compress(CompressFormat.JPEG, 100, fos); } catch (Exception e) { Log.d(LOG_TAG, "网络下载或保存文件失败"); e.printStackTrace(); } } protected String getFileSavePath() { String fileName = new SimpleDateFormat("yyyyMMdd hhmmss") .format(new Date()); String path = Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + "myAsycImage" + File.separator + "IMG_" + fileName + ".jpg"; File file = new File(path); if (!file.getParentFile().exists()) { if (!file.getParentFile().mkdirs()) { return null; } } try { file.createNewFile(); Log.d(LOG_TAG, file.getAbsolutePath()); return file.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); return null; } } // 定义一个回调接口 private interface ImageCallBack { void imageLoaded(Bitmap bitmap, ImageView imageView); } /** * 外部调用接口 * * @param uri * 网路上的图片地址 * @param imageView * 需要显示图片的image控件 * @param callback */ public void setAsycImageFromNet(String uri, ImageView imageView) { if (uri == null) { return; } imageView.setImageBitmap(loadBitmapFromNet(uri, imageView, new ImageCallBack() { @Override public void imageLoaded(Bitmap bitmap, ImageView imageView) { imageView.setImageBitmap(bitmap); } }, 2)); } public void setAsycImageFromSD(String path, ImageView imageView) { if (path == null) { return; } // 感觉是先用默认图片进行占位,等获取到图片再使用网路上的图片 imageView.setImageBitmap(loadBitmapFormSD(path, imageView, new ImageCallBack() { @Override public void imageLoaded(Bitmap bitmap, ImageView imageView) { imageView.setImageBitmap(bitmap); } }, 2)); } // 因为本地加载图片的时间开销小,因此可以不进行异步加载 public void setImageFromSD(String path, ImageView imageView) { imageView.setImageBitmap(BitmapFactory.decodeFile(path)); } }