package com.thankcreate.care.tool.ui;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import com.thankcreate.care.tool.misc.StringTool;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.ImageView;
public class DrawableManager {
private final WeakHashMap<String, Bitmap> drawableMap;
public WeakHashMap<String, Rect> adjustSizeMap;
public List<String> cancelList;
public DrawableManager() {
drawableMap = new WeakHashMap<String, Bitmap>();
adjustSizeMap = new WeakHashMap<String, Rect>();
cancelList = new ArrayList<String>();
}
public void removeFromCache(String url)
{
drawableMap.remove(url);
// 目前偷了一下懒,直接在removeFromCache里做了cancelReqeust了
cancelReqeuest(url);
}
public void cancelReqeuest(String url)
{
cancelList.add(url);
}
public Bitmap fetchDrawable(String urlString) {
// 一个主动的fetchDrawable过来后,需要把这个url从cancel列表中清除
cancelList.remove(urlString);
// 第一次查缓存
if (drawableMap.containsKey(urlString)) {
return drawableMap.get(urlString);
}
Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
try {
// 下面这一步可能是很耗时的,在这其间,什么都有可能发生
InputStream is = fetch(urlString);
if(cancelList.contains(urlString))
return null;
// 第二次查缓存
if (drawableMap.containsKey(urlString)) {
return drawableMap.get(urlString);
}
// 开始做decode
BitmapFactory.Options opt =new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inSampleSize = 1; //width,hight设为原来的一分之一
opt.inPurgeable = true;
opt.inInputShareable = true;
// 下面这一句其实才是OOM的根本所在,尽量避免无意义的decode
Bitmap bmp =BitmapFactory.decodeStream(is,null, opt);
// Drawable drawable = Drawable.createFromStream(is, "src");
// if (drawable != null) {
// drawableMap.put(urlString, drawable);
// Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
// + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
// + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
// } else {
// Log.w(this.getClass().getSimpleName(), "could not get thumbnail");
// }
if(bmp != null)
drawableMap.put(urlString, bmp);
return bmp;
} catch (MalformedURLException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
}
}
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
if(!isMatch(urlString, imageView))
{
return;
}
if (drawableMap.containsKey(urlString)) {
//imageView.setImageDrawable(drawableMap.get(urlString));
imageView.setImageBitmap(drawableMap.get(urlString));
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
if(!isMatch(urlString, imageView))
{
return;
}
// Drawable drawable = (Drawable) message.obj;
// imageView.setImageDrawable((Drawable) message.obj);
final Bitmap bmp = (Bitmap) message.obj;
imageView.setImageBitmap(drawableMap.get(urlString));
/**
* FIXME:纯Hack
* 原因:不知道为什么有时候这里明明bmp是有值的,但是更新到页面上去显示不出来
* 尤其是头像区,非常容易出现这种情况,invalidate了也没有用
* 这里直接作一个延时200ms,再刷新一次,看样子是解决了
*/
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
imageView.setImageBitmap(bmp);
}
}, 200);
}
};
Thread thread = new Thread() {
@Override
public void run() {
if(StringTool.isNullOrEmpty(urlString))
return;
Bitmap drawable = fetchDrawable(urlString);
if(drawable == null)
return;
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
};
thread.start();
}
public void fetchDrawableOnThreadWithCallback(final String urlString, final ImageView imageView, final FetchDrawableCompleteListener callback) {
if(!isMatch(urlString, imageView))
{
return;
}
if (drawableMap.containsKey(urlString)) {
callback.fetchComplete(drawableMap.get(urlString));
//imageView.setImageDrawable(drawableMap.get(urlString));
return;
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
if(!isMatch(urlString, imageView))
{
return;
}
//Drawable drawable = (Drawable) message.obj;
Bitmap bmp = (Bitmap) message.obj;
callback.fetchComplete(bmp);
//imageView.setImageDrawable((Drawable) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
//Drawable drawable = fetchDrawable(urlString);
Bitmap drawable = fetchDrawable(urlString);
if(drawable == null)
return;
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
};
thread.start();
}
public void fetchDrawableOnThreadWithDoNothing(final String urlString) {
if (drawableMap.containsKey(urlString)) {
return;
}
Thread thread = new Thread() {
@Override
public void run() {
fetchDrawable(urlString);
}
};
thread.start();
}
private Boolean isMatch(String urlString, ImageView imageView)
{
String url;
if(imageView.getTag() instanceof String)
{
url = (String) imageView.getTag();
if(urlString.compareToIgnoreCase(url) == 0)
{
return true;
}
return false;
}
else
{
return true;
}
}
public void fetchDrawableOnThread(final String urlString, final ImageView imageView, final int size, final Boolean needFit, final BaseAdapter adapter) {
if(!isMatch(urlString, imageView))
{
return;
}
if (drawableMap.containsKey(urlString)) {
//imageView.setImageDrawable(drawableMap.get(urlString));
imageView.setImageBitmap(drawableMap.get(urlString));
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
if(!isMatch(urlString, imageView))
{
return;
}
Bitmap bmp = (Bitmap) message.obj;
int sourceWidth = bmp.getWidth();
int sourceHeight = bmp.getHeight();
if(needFit)
{
LayoutParams params = imageView.getLayoutParams();
if(sourceWidth > sourceHeight)
{
int newHeight = size * sourceHeight / sourceWidth;
params.height = newHeight;
params.width = size;
imageView.setLayoutParams(params);
}
else if (sourceHeight >= sourceWidth)
{
int newWidth = size * sourceWidth / sourceHeight;
// 针对新浪微博超长图
if(newWidth < 20)
newWidth = 60;
params.width = newWidth;
params.height = size;
imageView.setLayoutParams(params);
}
Rect cacheRecht = new Rect(0, 0, params.width, params.height);
adjustSizeMap.put(urlString, cacheRecht);
}
imageView.setImageBitmap((Bitmap) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
Bitmap bmp = fetchDrawable(urlString);
if(bmp == null)
return;
if(!isMatch(urlString, imageView))
{
return;
}
Message message = handler.obtainMessage(1, bmp);
handler.sendMessage(message);
}
};
thread.start();
}
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(urlString);
HttpResponse response = httpClient.execute(request);
return response.getEntity().getContent();
}
public interface FetchDrawableCompleteListener
{
//public void fetchComplete(Drawable d);
public void fetchComplete(Bitmap d);
}
}