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;
}
}