/** * */ package cn.etong.util; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReference; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.os.AsyncTask; import android.os.Environment; import android.util.Log; import android.widget.ImageView; import cn.etong.data.NetProtocol; /** * @author jin001.wu@gmail.com <br> * @date 2012-9-4 * */ public class ImageLoader { private static final int MAX_THREAD = 5; private static final int MAX_IMAGE_QUEUE_SIZE = 20; private static final LinkedList<String> mFileWaitingList = new LinkedList<String>(); private static final HashSet<String> mFileRunningSet = new HashSet<String>(); private static final HashMap<String, Object> mFileWatitingValues = new HashMap<String, Object>(); public final static String TAG = "ImageLoader"; HashMap<String, SoftReference<Bitmap>> mImageBuffer = null; public final static String SDCARD_PICTURE_CACHE_PATH = "/com.etong.etong_cache/"; private final static long FIFTEEN_DAYS = 10 * 24 * 60 * 60 * 1000; public ImageLoader() { mImageBuffer = new HashMap<String, SoftReference<Bitmap>>(); // Create image cache directory in SDCard if (Util.checkSDCard()) { File file = new File(Environment.getExternalStorageDirectory() + SDCARD_PICTURE_CACHE_PATH); if (file != null && !file.exists()) { file.mkdir(); } } clearTempFiles(); } public void clearTempFiles() { if (Util.checkSDCard()) { File file = new File(Environment.getExternalStorageDirectory() + SDCARD_PICTURE_CACHE_PATH); if (file != null && file.exists()) { File[] filelist = file.listFiles(); File tempfile = null; for (int i = 0; i < filelist.length; i++) { tempfile = filelist[i]; // Delete the modified time is more than fifteen days if (System.currentTimeMillis() - tempfile.lastModified() > FIFTEEN_DAYS) { tempfile.delete(); } } } } } class CanvasImageTask extends AsyncTask<Object, Void, Bitmap> { /** After load picture, will set it to this view */ private SoftReference<Object> gView; /** According to this URL to down load picture */ private String url; /** Down load and generate bitmap object */ Bitmap bmp = null; /** Whether need write picture to cache */ private boolean mIsCache = true; public CanvasImageTask(boolean isCache) { mIsCache = isCache; } @Override protected Bitmap doInBackground(Object... str) { // Decode parameters url = str[0].toString(); if (str[1] != null) { gView = new SoftReference<Object>(str[1]); } if (!mImageBuffer.containsKey(url)) { // Load picture from local, SDCard or cache String fileName = Util.getImageName(url); File file = null; if (mIsCache) { file = new File(Global.G().getApp().getCacheDir(), fileName); } else { if (Util.checkSDCard()) { file = new File( Environment.getExternalStorageDirectory() + SDCARD_PICTURE_CACHE_PATH, fileName); } } // Decode bitmap according special director if (file != null && file.exists()) { bmp = tryToDecodeImageFile(file.getPath(), 1, true); } if (bmp != null) { mImageBuffer.put(url, new SoftReference<Bitmap>(bmp)); } else if (null != (bmp = loadImageFromUrl(url, file))) { // Down // load // from // network mImageBuffer.put(url, new SoftReference<Bitmap>(bmp)); } } return bmp; } @Override protected void onPostExecute(Bitmap bm) { if (bm != null) { Object gv = gView != null ? gView.get() : null; if (gv instanceof ImageView) { ImageView imageView = (ImageView) gv; imageView.setImageBitmap(bmp); } else if (gv instanceof ImageLoadListener) { ((ImageLoadListener) gv).onLoaded(url, bmp); } } mFileRunningSet.remove(url); if (mFileWaitingList.size() > 0) { for (;;) { if (mFileWaitingList.size() > 0) { String image = mFileWaitingList.removeFirst(); Object next = mFileWatitingValues.get(image); mFileWatitingValues.remove(image); if (next == null) { continue; } Object[] obj = (Object[]) next; Object gView = null; if (obj.length >= 2) { SoftReference<Object> ref = (SoftReference<Object>) obj[1]; if (ref != null) { gView = ref.get(); } } if (gView != null) { Object str[] = new Object[2]; str[0] = image; str[1] = gView; if (str != null) { new CanvasImageTask(false).execute(obj); } } } else { break; } } } } } public Bitmap getBitmap(String imageURL) { if (imageURL == null) { return null; } Bitmap bt = null; if (mImageBuffer.containsKey(imageURL)) { SoftReference<Bitmap> ref = mImageBuffer.get(imageURL); bt = ref.get(); } return bt; } public Bitmap getBitmap(final Object view, final String imageURL) { if (Util.isEmpty(imageURL)) { return null; } Bitmap bmp = null; if (mImageBuffer.containsKey(imageURL)) { bmp = mImageBuffer.get(imageURL).get(); if (bmp != null) { if (view instanceof ImageView) { ImageView imageView = (ImageView) view; imageView.setImageBitmap(bmp); } else if (view instanceof ImageLoadListener) { ((ImageLoadListener) view).onLoaded(imageURL, bmp); } else { Log.w(TAG, "Unkown view get bitmap!"); } return bmp; } } if (mFileRunningSet.contains(imageURL)) { Log.e("ImageCache", "inRunningSet"); } else if (mFileWaitingList.contains(imageURL)) { Log.e("ImageCache", "inWaitingSet"); } else { if (mFileRunningSet.size() > MAX_THREAD) { Object str[] = new Object[2]; str[0] = (imageURL); str[1] = new SoftReference<Object>(view); mFileWaitingList.add(imageURL); mFileWatitingValues.put(imageURL, str); if (mFileWaitingList.size() > MAX_IMAGE_QUEUE_SIZE) { mFileWaitingList.removeLast(); } } else { mFileRunningSet.add(imageURL); Object str[] = new Object[2]; str[0] = imageURL; str[1] = view; new CanvasImageTask(false).execute(str); } } return null; } public Bitmap loadingBitBitmap(Context context, String url) { if (url == null || url.length() == 0) { return null; } Bitmap bt = null; if (mImageBuffer.containsKey(url)) { SoftReference<Bitmap> ref = mImageBuffer.get(url); if (ref != null) { bt = ref.get(); } } if (bt != null) { return bt; } return readyLoad(context, url); } private Bitmap readyLoad(Context context, String url) { return readLoad(context, Environment.getExternalStorageDirectory() + SDCARD_PICTURE_CACHE_PATH, url); } private Bitmap readLoad(Context context, String path, String url) { Bitmap bmp = null; // Load picture from local, SDCard or cache String fileName = Util.getImageName(url); File file = null; file = new File(path, fileName); // Decode bitmap according special director if (file != null && file.exists()) { bmp = tryToDecodeImageFile(file.getPath(), 1, true); } if (bmp != null) { mImageBuffer.put(url, new SoftReference<Bitmap>(bmp)); } else if (null != (bmp = loadImageFromUrl(url, file))) { // Down load // from // network mImageBuffer.put(url, new SoftReference<Bitmap>(bmp)); } return bmp; } public void releaseBitmap(String url) { if (mImageBuffer.containsKey(url)) { Bitmap bmp = mImageBuffer.get(url).get(); if (bmp != null) { try { bmp.recycle(); } catch (RuntimeException e) { // TODO: handle exception e.printStackTrace(); } } bmp = null; mImageBuffer.remove(url); } } private Bitmap loadImageFromUrl(String urlString, File file) { urlString = NetProtocol.DOMAIN_URL + urlString; Bitmap bitmap = null; HttpURLConnection conn = null; InputStream is = null; try { URL url = new URL(urlString); conn = (HttpURLConnection) url.openConnection(); is = conn.getInputStream(); // Get the length int length = (int) conn.getContentLength(); if (length != -1) { byte[] imgData = new byte[length]; byte[] temp = new byte[1024]; int readLen = 0; int destPos = 0; while ((readLen = is.read(temp)) > 0) { System.arraycopy(temp, 0, imgData, destPos, readLen); destPos += readLen; } bitmap = BitmapFactory.decodeByteArray(imgData, 0, imgData.length); // Save to cache if (file != null) { writeBitmapToCache(imgData, file); } } else { Log.i(TAG, "no length!"); bitmap = BitmapFactory.decodeStream(is); } if (is != null) { is.close(); } if (conn != null) { conn.disconnect(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (OutOfMemoryError e) { e.printStackTrace(); } return bitmap; } public void writeBitmap(Bitmap bit, String url) { if (bit == null || Util.isEmpty(url)) { return; } String fileName = Util.getImageName(url); File file = new File(Environment.getExternalStorageDirectory() + SDCARD_PICTURE_CACHE_PATH, fileName); ByteArrayOutputStream baos = new ByteArrayOutputStream(); bit.compress(Bitmap.CompressFormat.JPEG, 100, baos); writeBitmapToCache(baos.toByteArray(), file); } private void writeBitmapToCache(byte[] imgData, File file) { FileOutputStream fos = null; BufferedOutputStream outPutBuffer = null; if (file != null) { try { fos = new FileOutputStream(file); outPutBuffer = new BufferedOutputStream(fos); outPutBuffer.write(imgData); outPutBuffer.flush(); fos.flush(); } catch (IOException e) { Log.e(TAG, e.toString()); } finally { try { if (fos != null) { fos.close(); } if (outPutBuffer != null) { outPutBuffer.close(); } } catch (IOException e) { Log.e(TAG, e.toString()); } } } } public static Bitmap tryToDecodeImageFile(String filePath, int quanlity, boolean autoCompress) { Bitmap bitmap = null; try { if (quanlity == 1) { bitmap = BitmapFactory.decodeFile(filePath); } else { BitmapFactory.Options options = new Options(); options.inSampleSize = quanlity; bitmap = BitmapFactory.decodeFile(filePath, options); } } catch (OutOfMemoryError oe) { /* * if(autoCompress){ int rate = (quanlity >= 4) ? 2 : 4; Log.d(TAG, * "Decode the file automatically with quanlity :" + quanlity * * rate); bitmap = tryToDecodeImageFile(filePath, quanlity * rate, * false); }else{ Log.e(TAG, * "Decode the file failed!, out of memory!"); oe.printStackTrace(); * } */ } catch (Exception e) { e.printStackTrace(); } return bitmap; } public static interface ImageLoadListener { void onLoaded(String url, Bitmap bt); } }
(用法
if (!Util.isEmpty(image)) {
Global.G().getImageLoader().getBitmap(mWeatherImage, image);
}
)