package com.quark.http.image; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.concurrent.ConcurrentHashMap; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.net.http.AndroidHttpClient; import android.os.AsyncTask; import android.os.Handler; import android.util.Log; import android.widget.BaseAdapter; import com.qingmu.jianzhidaren.R; import com.quark.adapter.BaomingAdapter.ViewHolder; public class BaomingImageLoader { private static final String TAG = "ImageLoader"; private static final int MAX_CAPACITY = 50;// 一级缓存的最大空间 private static final long DELAY_BEFORE_PURGE = 100 * 1000;// 定时清理缓存 // 0.75是加载因子为经验值,true则表示按照最近访问量的高低排序,false则表示按照插入顺序排序 private static HashMap<String, Bitmap> mFirstLevelCache = new LinkedHashMap<String, Bitmap>( MAX_CAPACITY / 2, 0.75f, true) { private static final long serialVersionUID = 1L; protected boolean removeEldestEntry(Entry<String, Bitmap> eldest) { if (size() > MAX_CAPACITY) {// 当超过一级缓存阈值的时候,将老的值从一级缓存搬到二级缓存 mSecondLevelCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue())); return true; } return false; }; }; // 二级缓存,采用的是软应用,只有在内存吃紧的时候软应用才会被回收,有效的避免了oom private static ConcurrentHashMap<String, SoftReference<Bitmap>> mSecondLevelCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>( MAX_CAPACITY / 2); // 定时清理缓存 private static Runnable mClearCache = new Runnable() { @Override public void run() { clear(); } }; private static Handler mPurgeHandler = new Handler(); // 重置缓存清理的timer private static void resetPurgeTimer() { mPurgeHandler.removeCallbacks(mClearCache); mPurgeHandler.postDelayed(mClearCache, DELAY_BEFORE_PURGE); } /** * 清理缓存 */ private static void clear() { mFirstLevelCache.clear(); mSecondLevelCache.clear(); } /** * 返回缓存,如果没有则返回null * * @param url * @return */ public static Bitmap getBitmapFromCache(String url) { Bitmap bitmap = null; bitmap = getFromFirstLevelCache(url);// 从一级缓存中拿 if (bitmap != null) { return bitmap; } bitmap = getFromSecondLevelCache(url);// 从二级缓存中拿 return bitmap; } /** * 从二级缓存中拿 * * @param url * @return */ private static Bitmap getFromSecondLevelCache(String url) { Bitmap bitmap = null; SoftReference<Bitmap> softReference = mSecondLevelCache.get(url); if (softReference != null) { bitmap = softReference.get(); if (bitmap == null) {// 由于内存吃紧,软引用已经被gc回收了 mSecondLevelCache.remove(url); } } return bitmap; } /** * 从一级缓存中拿 * * @param url * @return */ private static Bitmap getFromFirstLevelCache(String url) { Bitmap bitmap = null; synchronized (mFirstLevelCache) { bitmap = mFirstLevelCache.get(url); if (bitmap != null) {// 将最近访问的元素放到链的头部,提高下一次访问该元素的检索速度(LRU算法) mFirstLevelCache.remove(url); mFirstLevelCache.put(url, bitmap); } } return bitmap; } /** * 加载图片,如果缓存中有就直接从缓存中拿,缓存中没有就下载 * * @param url * @param adapter * @param holder */ public static void loadImage(String url, BaseAdapter adapter, ViewHolder holder) { resetPurgeTimer(); Bitmap bitmap = getBitmapFromCache(url);// 从缓存中读取 if (bitmap == null) { holder.bm_headpic.setImageResource(R.drawable.ic_launcher);// 缓存没有设为默认图片 ImageLoadTask imageLoadTask = new ImageLoadTask(); imageLoadTask.execute(url, adapter, holder); } else { holder.bm_headpic.setImageBitmap(bitmap);// 设为缓存图片 } } public static Bitmap toRoundCorner(Bitmap bitmap, float pixels) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); final float roundPx = pixels; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, bitmap.getWidth() / pixels, bitmap.getHeight() / pixels, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; } /** * 放入缓存 * * @param url * @param value */ public static void addImage2Cache(String url, Bitmap value) { if (value == null || url == null) { return; } synchronized (mFirstLevelCache) { mFirstLevelCache.put(url, value); } } static class ImageLoadTask extends AsyncTask<Object, Void, Bitmap> { String url; BaseAdapter adapter; @Override protected Bitmap doInBackground(Object... params) { url = (String) params[0]; adapter = (BaseAdapter) params[1]; Bitmap drawable = loadImageFromInternet(url);// 获取网络图片 return drawable; } @Override protected void onPostExecute(Bitmap result) { if (result == null) { return; } addImage2Cache(url, result);// 放入缓存 adapter.notifyDataSetChanged();// 触发getView方法执行,这个时候getView实际上会拿到刚刚缓存好的图片 } } public static Bitmap loadImageFromInternet(String url) { Bitmap bitmap = null; HttpClient client = AndroidHttpClient.newInstance("Android"); HttpParams params = client.getParams(); HttpConnectionParams.setConnectionTimeout(params, 3000); HttpConnectionParams.setSocketBufferSize(params, 3000); HttpResponse response = null; InputStream inputStream = null; HttpGet httpGet = null; try { httpGet = new HttpGet(url); response = client.execute(httpGet); int stateCode = response.getStatusLine().getStatusCode(); if (stateCode != HttpStatus.SC_OK) { Log.d(TAG, "func [loadImage] stateCode=" + stateCode); return bitmap; } HttpEntity entity = response.getEntity(); if (entity != null) { try { inputStream = entity.getContent(); // carson 压缩图片防止oom BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = false; options.inSampleSize = 4; return bitmap = BitmapFactory.decodeStream(inputStream, null, options); } finally { if (inputStream != null) { inputStream.close(); } entity.consumeContent(); } } } catch (ClientProtocolException e) { httpGet.abort(); e.printStackTrace(); } catch (IOException e) { httpGet.abort(); e.printStackTrace(); } finally { ((AndroidHttpClient) client).close(); } return bitmap; } }