ImageLoader

来源:互联网 发布:淘宝装修模板怎么使用 编辑:程序博客网 时间:2024/04/30 05:34
import java.io.BufferedOutputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLEncoder;import java.util.Iterator;import java.util.LinkedList;import java.util.Queue;import java.util.Stack;import com.siso.dy.buyenough.constant.Constant;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.BitmapFactory;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.graphics.drawable.TransitionDrawable;import android.media.ThumbnailUtils;import android.os.Environment;import android.os.Handler;import android.os.HandlerThread;import android.os.Looper;import android.os.Message;import android.support.v4.util.LruCache;import android.text.TextUtils;import android.widget.ImageView;/** * 图片加载类 */public class ImageLoader {private static ImageLoader instance;public LruCache<String, Bitmap> mMemoryCache;/** 图片加载队列,后进先出 */private Stack<ImageRef> mImageQueue = new Stack<ImageRef>();/** 图片请求队列,先进先出,用于存放已发送的请求。 */private Queue<ImageRef> mRequestQueue = new LinkedList<ImageRef>();/** 图片加载线程消息处理器 */private Handler mImageLoaderHandler;/** 图片加载线程是否就绪 */private boolean mImageLoaderIdle = true;/** 请求图片 */private static final int MSG_REQUEST = 1;/** 图片加载完成 */private static final int MSG_REPLY = 2;/** 中止图片加载线程 */private static final int MSG_STOP = 3;/** 如果图片是从网络加载,则应用渐显动画,如果从缓存读出则不应用动画 */private boolean isFromNet = true;private static final String CACHE_PATH = Environment.getExternalStoragePublicDirectory(Constant.IMGURL).getAbsolutePath();/** * 获取单例,只能在UI线程中使用。 *  * @return */public static ImageLoader getInst() {// 如果不在ui线程中,则抛出异常if (Looper.myLooper() != Looper.getMainLooper()) {throw new RuntimeException("Cannot instantiate outside UI thread.");}if (instance == null) {synchronized (ImageLoader.class) {if (instance == null) {instance = new ImageLoader();}}}return instance;}/** * 私有构造函数,保证单例模式 *  * @param context */private ImageLoader() {long maxMemory = Runtime.getRuntime().maxMemory();long cacheSize = maxMemory / 8;mMemoryCache = new LruCache<String, Bitmap>((int) cacheSize) {protected int sizeOf(String key, Bitmap bitmap) {return bitmap.getRowBytes() * bitmap.getHeight();}};File f = new File(CACHE_PATH);if (!f.exists()) {f.mkdirs();}}/** * 存放图片信息 */class ImageRef {/** 图片对应ImageView控件 */ImageView imageView;/** 图片URL地址 */String url;/** 图片缓存路径 */String filePath;/** 默认图资源ID */int resId;int width = 0;int height = 0;/** * 构造函数 *  * @param imageView * @param url * @param resId * @param filePath */ImageRef(ImageView imageView, String url, String filePath, int resId) {this.imageView = imageView;this.url = url;this.filePath = filePath;this.resId = resId;}ImageRef(ImageView imageView, String url, String filePath, int resId,int width, int height) {this.imageView = imageView;this.url = url;this.filePath = filePath;this.resId = resId;this.width = width;this.height = height;}}/** * 显示图片 *  * @param imageView * @param url * @param resId */public void displayImage(ImageView imageView, String url, int resId) {if (imageView == null) {return;}//try {//url = URLEncoder.encode(url,"utf-8").replaceAll("\\+", "%20");//} catch (UnsupportedEncodingException e) {//// TODO Auto-generated catch block//e.printStackTrace();//}//url = Constants.IP_01 + "/" + url;if (imageView.getTag() != null&& imageView.getTag().toString().equals(url)) {return;}if (resId >= 0) {if (imageView.getBackground() == null) {imageView.setBackgroundResource(resId);}imageView.setImageDrawable(null);}if (TextUtils.isEmpty(url)) {return;}// 添加url tagimageView.setTag(url);// 读取map缓存Bitmap bitmap = mMemoryCache.get(url);if (bitmap != null) {setImageBitmap(imageView, bitmap, false);return;}// 生成文件名String filePath = urlToFilePath(url);if (filePath == null) {return;}queueImage(new ImageRef(imageView, url, filePath, resId));}/** * 显示图片固定大小图片的缩略图,一般用于显示列表的图片,可以大大减小内存使用 *  * @param imageView *            加载图片的控件 * @param url *            加载地址 * @param resId *            默认图片 * @param width *            指定宽度 * @param height *            指定高度 */public void displayImage(ImageView imageView, String url, int resId,int width, int height) {if (imageView == null) {return;}//url = Constants.IP_01 + "/" + url;if (resId >= 0) {if (imageView.getBackground() == null) {imageView.setBackgroundResource(resId);}imageView.setImageDrawable(null);}if (TextUtils.isEmpty(url)) {return;}// 添加url tagimageView.setTag(url);// 读取map缓存Bitmap bitmap = null;if (width > 0 && height > 0) {bitmap = mMemoryCache.get(url+width+height);// } else {bitmap = mMemoryCache.get(url);}if (bitmap != null) {setImageBitmap(imageView, bitmap, false);return;}// 生成文件名String filePath = urlToFilePath(url);if (filePath == null) {return;}queueImage(new ImageRef(imageView, url, filePath, resId, width, height));}/** * 入队,后进先出 *  * @param imageRef */public void queueImage(ImageRef imageRef) {// 删除已有ImageViewIterator<ImageRef> iterator = mImageQueue.iterator();while (iterator.hasNext()) {if (iterator.next().imageView == imageRef.imageView) {iterator.remove();}}// 添加请求mImageQueue.push(imageRef);sendRequest();}/** * 发送请求 */private void sendRequest() {// 开启图片加载线程if (mImageLoaderHandler == null) {HandlerThread imageLoader = new HandlerThread("image_loader");imageLoader.start();mImageLoaderHandler = new ImageLoaderHandler(imageLoader.getLooper());}// 发送请求if (mImageLoaderIdle && mImageQueue.size() > 0) {ImageRef imageRef = mImageQueue.pop();Message message = mImageLoaderHandler.obtainMessage(MSG_REQUEST,imageRef);mImageLoaderHandler.sendMessage(message);mImageLoaderIdle = false;mRequestQueue.add(imageRef);}}/** * 图片加载线程 */class ImageLoaderHandler extends Handler {public ImageLoaderHandler(Looper looper) {super(looper);}public void handleMessage(Message msg) {if (msg == null)return;switch (msg.what) {case MSG_REQUEST: // 收到请求Bitmap bitmap = null;Bitmap tBitmap = null;if (msg.obj != null && msg.obj instanceof ImageRef) {ImageRef imageRef = (ImageRef) msg.obj;String url = imageRef.url;if (url == null)return;bitmap = getBitmapFromSdcard(imageRef.filePath,imageRef.width, imageRef.height);if (bitmap != null) {// ToolUtil.log("从disk缓存读取");// 写入map缓存if (imageRef.width > 0 && imageRef.height > 0) {if (mMemoryCache.get(url + imageRef.width+ imageRef.height) == null)mMemoryCache.put(url + imageRef.width+ imageRef.height, bitmap);} else {if (mMemoryCache.get(url) == null)mMemoryCache.put(url, bitmap);}} else {try {byte[] data = loadByteArrayFromNetwork(url);if (data != null) {BitmapFactory.Options opt = new BitmapFactory.Options();opt.inSampleSize = 1;opt.inJustDecodeBounds = true;BitmapFactory.decodeByteArray(data, 0,data.length, opt);int bitmapSize = opt.outHeight * opt.outWidth* 4;// pixels*3 if it's RGB and pixels*4// if it's ARGBif (bitmapSize > 1000 * 1200)opt.inSampleSize = 2;opt.inJustDecodeBounds = false;tBitmap = BitmapFactory.decodeByteArray(data,0, data.length, opt);if (imageRef.width != 0 && imageRef.height != 0) {bitmap = ThumbnailUtils.extractThumbnail(tBitmap,imageRef.width,imageRef.height,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);} else {bitmap = tBitmap;tBitmap = null;}if (bitmap != null && url != null) {// 写入SD卡if (imageRef.width > 0&& imageRef.height > 0) {writeBitmapToFile(bitmap,imageRef.filePath+ imageRef.width+ imageRef.height);mMemoryCache.put(url + imageRef.width+ imageRef.height, bitmap);} else {writeBitmapToFile(bitmap,imageRef.filePath);mMemoryCache.put(url, bitmap);}isFromNet = true;}}} catch (OutOfMemoryError e) {}}}if (mImageManagerHandler != null) {Message message = mImageManagerHandler.obtainMessage(MSG_REPLY, bitmap);mImageManagerHandler.sendMessage(message);}break;case MSG_STOP: // 收到终止指令Looper.myLooper().quit();break;}}}/** UI线程消息处理器 */private Handler mImageManagerHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg != null) {switch (msg.what) {case MSG_REPLY: // 收到应答do {ImageRef imageRef = mRequestQueue.remove();if (imageRef == null)break;if (imageRef.imageView == null|| imageRef.imageView.getTag() == null|| imageRef.url == null)break;if (!(msg.obj instanceof Bitmap) || msg.obj == null) {break;}Bitmap bitmap = (Bitmap) msg.obj;// 非同一ImageViewif (!(imageRef.url).equals((String) imageRef.imageView.getTag())) {break;}setImageBitmap(imageRef.imageView, bitmap, isFromNet);isFromNet = false;} while (false);break;}}// 设置闲置标志mImageLoaderIdle = true;// 若服务未关闭,则发送下一个请求。if (mImageLoaderHandler != null) {sendRequest();}}};/** * 添加图片显示渐现动画 *  */private void setImageBitmap(ImageView imageView, Bitmap bitmap,boolean isTran) {if (isTran) {final TransitionDrawable td = new TransitionDrawable(new Drawable[] {new ColorDrawable(android.R.color.transparent),new BitmapDrawable(bitmap) });td.setCrossFadeEnabled(true);imageView.setImageDrawable(td);td.startTransition(300);} else {imageView.setImageBitmap(bitmap);}}/** * 从网络获取图片字节数组 *  * @param url * @return */private byte[] loadByteArrayFromNetwork(String url) {try {// HttpGet method = new HttpGet(url);// HttpResponse response = myapp.getHttpClient().execute(method);// HttpEntity entity = response.getEntity();// return EntityUtils.toByteArray(entity);URL imageUrl = null;InputStream is = null;HttpURLConnection conn = null;imageUrl = new URL(url);conn = (HttpURLConnection) imageUrl.openConnection();is = conn.getInputStream();ByteArrayOutputStream baos = new ByteArrayOutputStream();int len = 0;byte[] b = new byte[1024];while ((len = is.read(b, 0, b.length)) != -1) {baos.write(b, 0, len);}return baos.toByteArray();} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (Exception e) {}return null;}/** * 根据url生成缓存文件完整路径名 *  * @param url * @return */public String urlToFilePath(String url) {// 扩展名位置int index = url.lastIndexOf('.');if (index == -1) {return null;}StringBuilder filePath = new StringBuilder();// 图片存取路径filePath.append(CACHE_PATH).append('/');// 图片文件名filePath.append(Md5Utils.md5(url));return filePath.toString();}/** * Activity#onStop后,ListView不会有残余请求。 */public void stop() {// 清空请求队列mImageQueue.clear();}private Bitmap getBitmapFromSdcard(String filePath, int width, int height) {File f = null;if (width > 0 && height > 0) {f = new File(filePath + width + height);} else {f = new File(filePath);}if (f.exists()) {return BitmapFactory.decodeFile(filePath);}return null;}private boolean writeBitmapToFile(Bitmap bitmap, String file) {OutputStream out = null;try {out = new BufferedOutputStream(new FileOutputStream(file), 4096);return bitmap.compress(CompressFormat.PNG, 100, out);} catch (FileNotFoundException fe) {} finally {if (out != null) {try {out.close();} catch (IOException e) {e.printStackTrace();}}}return false;}// public static void displayBigImage(ImageView imageView, String name,// int defaultResId) {// getInst().displayImage(imageView, Constant.IP + "/" + name,// defaultResId);// }//// public static void displaySmallImage(ImageView imageView, String name,// int defaultResId) {// getInst().displayImage(imageView, Constant.IP + "/" + name,// defaultResId);// }}


调用方法

ImageLoader.getInst().displayImageimageview,url, R.drawable.iv_basemap);
 R.drawable.iv_basemap,这个是获取不到图片时候的默认图片

0 0
原创粉丝点击