Android开源客户端之LookAround学习(二) 图片异步加载

来源:互联网 发布:qq玫瑰小镇辅助软件 编辑:程序博客网 时间:2024/06/05 20:48

图片加载,使用了内存缓存、文件缓存等方法。效果还不错。下图为加载图片时的流程图。



下面为该图片加载类:

package com.geniusgithub.lookaround.cache;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;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.geniusgithub.lookaround.util.CommonLog;import com.geniusgithub.lookaround.util.LogFactory;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.util.Log;import android.widget.ImageView;/** * 图片下载类 *  * @author Administrator *  */public class ImageLoaderEx {private static final CommonLog log = LogFactory.createLog();private MemoryCache memoryCache = new MemoryCache();private AbstractFileCache fileCache;private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());// 线程池private ExecutorService executorService;private int requestSize = 120;private Bitmap mDefaultBitmap = null;private boolean mIsLoadLocalBitmapQuick = false;/** * 构造函数 *  * @param context */public ImageLoaderEx(Context context) {fileCache = new FileCache(context);executorService = Executors.newFixedThreadPool(5);}/** * 设置图片大小 *  * @param request_size */public void setScaleParam(int request_size) {requestSize = request_size;log.e("setScaleParam requestSize = " + requestSize);}/** * 是否快速下载图片 *  * @param flag */public void setLoadLocalBitmapQuick(boolean flag) {mIsLoadLocalBitmapQuick = flag;}/** * 设置默认图片 *  * @param drawable */public void setDefaultBitmap(Drawable drawable) {if (drawable != null) {BitmapDrawable bd = (BitmapDrawable) drawable;mDefaultBitmap = bd.getBitmap();}}/** * 最主要的方法 *  * @param url * @param imageView * @param isLoadOnlyFromCache * @return */public boolean DisplayImage(String url, ImageView imageView,boolean isLoadOnlyFromCache) {if (url == null || url.length() < 1 || imageView == null) {return false;}imageViews.put(imageView, url);// 先从内存缓存中查找Bitmap bitmap = memoryCache.get(url);if (bitmap != null) {imageView.setImageBitmap(bitmap);return true;}// 如果直接从缓存文件加载if (mIsLoadLocalBitmapQuick) {File f = fileCache.getFile(url);// 先从文件缓存中查找是否有Bitmap b = null;if (f != null && f.exists()) {b = decodeFile(f);}if (b != null) {imageView.setImageBitmap(b);return true;}}if (mDefaultBitmap != null) {imageView.setImageBitmap(mDefaultBitmap);}if (!isLoadOnlyFromCache) {// 若没有的话则开启新线程加载图片queuePhoto(url, imageView);}return false;}/** * 同步加载图片 *  * @param url * @param imageView * @return */public boolean syncLoadBitmap(String url, ImageView imageView) {if (url == null || url.length() < 1 || imageView == null) {return false;}queuePhoto(url, imageView);return true;}/** * 线程池启动线程加载图片 *  * @param url * @param imageView */private void queuePhoto(String url, ImageView imageView) {PhotoToLoad p = new PhotoToLoad(url, imageView);executorService.submit(new PhotosLoader(p));}/** * 获取图片 *  * @param url * @return */private Bitmap getBitmap(String url) {File f = fileCache.getFile(url);// 先从文件缓存中查找是否有Bitmap b = null;if (f != null && f.exists()) {b = decodeFile(f);}if (b != null) {return b;}// 最后从指定的url中下载图片try {Bitmap bitmap = null;URL imageUrl = new URL(url);HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();conn.setConnectTimeout(30000);conn.setReadTimeout(30000);conn.setInstanceFollowRedirects(true);InputStream is = conn.getInputStream();OutputStream os = new FileOutputStream(f);CopyStream(is, os);os.close();bitmap = decodeFile(f);return bitmap;} catch (Exception ex) {Log.e("","getBitmap catch Exception...\nmessage = "+ ex.getMessage());return null;}}/** * decode这个图片并且按比例缩放以减少内存消耗,虚拟机对每张图片的缓存大小也是有限制的 *  * @param f * @return */private Bitmap decodeFile(File f) {try {// decode image sizeBitmapFactory.Options o = new BitmapFactory.Options();o.inJustDecodeBounds = true;BitmapFactory.decodeStream(new FileInputStream(f), null, o);// Find the correct scale value. It should be the power of 2.int width_tmp = o.outWidth, height_tmp = o.outHeight;int scale = 1;while (true) {if (width_tmp / 2 < requestSize || height_tmp / 2 < requestSize)break;width_tmp /= 2;height_tmp /= 2;scale *= 2;}// log.e("w = " + width_tmp + ", h = " + height_tmp + ", scale = " +// scale);// decode with inSampleSizeBitmapFactory.Options o2 = new BitmapFactory.Options();o2.inSampleSize = scale;return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);} catch (FileNotFoundException e) {}return null;}/** * 下载图片类 Task for the queue *  * @author Administrator *  */private class PhotoToLoad {public String url;public ImageView imageView;public PhotoToLoad(String u, ImageView i) {url = u;imageView = i;}}/** * 图片下载线程执行函数 */class PhotosLoader implements Runnable {PhotoToLoad photoToLoad;/** * 构造函数 */PhotosLoader(PhotoToLoad photoToLoad) {this.photoToLoad = photoToLoad;}@Overridepublic void run() {if (imageViewReused(photoToLoad)) {return;}Bitmap bmp = getBitmap(photoToLoad.url);memoryCache.put(photoToLoad.url, bmp);if (imageViewReused(photoToLoad))return;BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);// 更新的操作放在UI线程中Activity a = (Activity) photoToLoad.imageView.getContext();a.runOnUiThread(bd);}}/** * 防止图片错位 *  * @param photoToLoad * @return */boolean imageViewReused(PhotoToLoad photoToLoad) {String tag = imageViews.get(photoToLoad.imageView);if (tag == null || !tag.equals(photoToLoad.url))return true;return false;}// 用于在UI线程中更新界面class BitmapDisplayer implements Runnable {Bitmap bitmap;PhotoToLoad photoToLoad;public BitmapDisplayer(Bitmap b, PhotoToLoad p) {bitmap = b;photoToLoad = p;}public void run() {// log.e("BitmapDisplayer run...");if (imageViewReused(photoToLoad))return;if (bitmap != null)photoToLoad.imageView.setImageBitmap(bitmap);}}/** * 清楚缓存 */public void clearCache() {memoryCache.clear();fileCache.clear();}/** * 拷贝接收到的数据 *  * @param is * @param os */public static void CopyStream(InputStream is, OutputStream os) {final int buffer_size = 1024;try {byte[] bytes = new byte[buffer_size];for (;;) {int count = is.read(bytes, 0, buffer_size);if (count == -1)break;os.write(bytes, 0, count);}} catch (Exception ex) {Log.e("", "CopyStream catch Exception...");}}}

使用该类的示例如下:


mImageLoader.DisplayImage(url, imageView, true);

0 0
原创粉丝点击