package com.simtice.cnbeta.util.imagecache; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.simtice.cnbeta.util.Constant; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.text.TextUtils; import android.widget.ImageView; import android.widget.ImageView.ScaleType; /** * 图片异步加载器 * * @author xxf * */ public class ImageAsynLoader { private static MemoryCache memoryCache; private static ExecutorService executorService; private static FileCache fileCache; private static Map<ImageView, String> imageViews; private boolean isThumb; private int resWidth = 100; private int resHeight = 100; private ScaleType type = ScaleType.FIT_XY; /** * @param context */ public ImageAsynLoader(Context context) { fileCache = new FileCache(Constant.dirName); } /** * 是否保存在缩略图目录 * * @param isThumb * true:保存在thumbnails目录下,false:保存在files目录下 */ public void isSaveThumb(boolean isThumb) { this.isThumb = isThumb; } static { memoryCache = new MemoryCache(); executorService = Executors.newFixedThreadPool(5); imageViews = Collections .synchronizedMap(new WeakHashMap<ImageView, String>()); } /** * 指定宽高从本地读取图片,默认为100 * * @param resWidth * @param resHeight */ public void setDecodeSize(int resWidth, int resHeight) { this.resHeight = resHeight; this.resWidth = resWidth; } /** * 加载图片 * * @param url * @param imageView * @param isLoadOnlyFromCache * @param defaultBitmap */ public void displayImage(String url, ImageView imageView, boolean isLoadOnlyFromCache, Bitmap defaultBitmap) { if (!TextUtils.isEmpty(url)) { imageViews.put(imageView, url); imageView.setImageBitmap(defaultBitmap); imageView.setScaleType(ScaleType.CENTER_INSIDE); Bitmap bitmap = memoryCache.get(url); if (bitmap != null) { imageView.setScaleType(type); imageView.setImageBitmap(bitmap); } else queueLoad(url, imageView, isLoadOnlyFromCache); } } //设置图片加载之后的ScaleType 默认ScaleType.FIT_XY public void setImageScaleType(ScaleType type){ this.type = type; } /** * 创建文件缓存目录 */ public void createFileCacheDir() { fileCache.creatCacheDir(isThumb); } /** * 从本地缓存或者网络加载图片 * * @param url * @param imageView * @param isLoadOnlyFromCache * 是否仅仅从缓存加载图片 */ private void queueLoad(String url, ImageView imageView, boolean isLoadOnlyFromCache) { if (!fileCache.isCacheDirExis()) { createFileCacheDir(); } ImageLoadBean bean = new ImageLoadBean(); bean.setImageView(imageView); bean.setLoadOnlyFromCache(isLoadOnlyFromCache); bean.setUrl(url); executorService.execute(new GetBitmap(bean)); // executorService.submit(new GetBitmap(bean)); } /** * 线程获取图片 * * @author simtice * */ private class GetBitmap implements Runnable { private ImageLoadBean bean; public GetBitmap(ImageLoadBean bean) { this.bean = bean; } @Override public void run() { try { if (imageViewReused(bean)) { return; } Bitmap bitmap = getBitmap(bean.getUrl(), this.bean.getIsLoadOnlyFromCache()); if (bitmap != null) { memoryCache.put(bean.getUrl(), bitmap); Activity activity = (Activity) bean.getImageView() .getContext(); activity.runOnUiThread(new BitmapDisplayer(bitmap, bean)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // 用于在UI线程中更新界面 class BitmapDisplayer implements Runnable { private Bitmap bitmap; private ImageLoadBean imageLoadBean; public BitmapDisplayer(Bitmap b, ImageLoadBean p) { bitmap = b; imageLoadBean = p; } @Override public void run() { if (imageViewReused(imageLoadBean)) return; imageLoadBean.getImageView().setScaleType(type); imageLoadBean.getImageView().setImageBitmap(bitmap); } } private Bitmap getBitmap(String url, boolean isLoadOnlyFromCache) throws IOException { File file = fileCache.getFile(url); if (file != null && file.exists()) { return ImageUtil.decodeImage(file, resWidth, resHeight); } if (!isLoadOnlyFromCache) { downloadImage(url, file); return ImageUtil.decodeImage(file, resWidth, resHeight); } return null; } private class ImageLoadBean { private String url; private ImageView imageView; private boolean isLoadOnlyFromCache; public boolean getIsLoadOnlyFromCache() { return isLoadOnlyFromCache; } public void setLoadOnlyFromCache(boolean isLoadOnlyFromCache) { this.isLoadOnlyFromCache = isLoadOnlyFromCache; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public ImageView getImageView() { return imageView; } public void setImageView(ImageView imageView) { this.imageView = imageView; } } /** * 清除缓存 */ public void clearCache() { memoryCache.clear(); // fileCache.clear(dirName); imageViews.clear(); } /** * 防止图片错位 * * @param imageLoadBean * @return */ private boolean imageViewReused(ImageLoadBean imageLoadBean) { String tag = imageViews.get(imageLoadBean.getImageView()); if (tag == null || !tag.equals(imageLoadBean.getUrl())) return true; return false; } /** * 下载图片 * * @param urlStr * @param file */ private void downloadImage(final String urlStr, File file) { InputStream is = null; OutputStream os = null; try { URL url = new URL(urlStr); HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setConnectTimeout(5000); connection.setReadTimeout(5000); is = connection.getInputStream(); os = new FileOutputStream(file); int count = 0; final int bufferSize = 1024; byte buffer[] = new byte[bufferSize]; while ((count = is.read(buffer, 0, bufferSize)) != -1) { os.write(buffer, 0, count); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null && is != null) { os.close(); is.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }