package reco.frame.tv.view.component;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.os.Handler;
import android.renderscript.Int2;
import android.support.v4.util.LruCache;
import android.support.v4.util.SparseArrayCompat;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
public class RecycleBin {
private final static String TAG = "RecycleBin";
public final static int STATE_ACTIVE = 0, STATE_SCRAP = 1;
public static LruCache<String, Bitmap> mLruCache;
private String cachedDir;
// �̳߳�
private static ExecutorService sExecutorService;
// ֪ͨUI�߳�ͼƬ��ȡokʱʹ��
private Handler handler;
// �洢���ڻ���״̬��item ID ������ͼƬ�ؼ�ID
// private static SparseIntArray recycleIds;
// ״̬��¼
private static SparseIntArray itemStates;
// �洢���ڻ���״̬��item ID ������ͼƬ�ؼ�ID
private Map<Integer, HashSet<Integer>> recycleIds;
private final static int STATE_RECYCLING = 1, STATE_RELOADING = 2;
public RecycleBin(String cachedDir) {
this.cachedDir = cachedDir;
handler = new Handler();
// recycleIds = new SparseIntArray();
itemStates = new SparseIntArray();
initLruCache();
startThreadPoolIfNecessary();
recycleIds = new HashMap<Integer, HashSet<Integer>>();
}
private static void initLruCache() {
if (mLruCache == null) {
// ��ȡ�������ڴ�����ֵ��ʹ���ڴ泬�����ֵ������OutOfMemory�쳣��
// LruCacheͨ�����캯�����뻺��ֵ����KBΪ��λ��
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// ʹ���������ڴ�ֵ��1/6��Ϊ����Ĵ�С��
int cacheSize = maxMemory / 6;
mLruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// ��д�˷���������ÿ��ͼƬ�Ĵ�С��Ĭ�Ϸ���ͼƬ������
return bitmap.getByteCount() / 1024;
}
};
}
}
/** �����̳߳� */
public static void startThreadPoolIfNecessary() {
if (sExecutorService == null || sExecutorService.isShutdown()
|| sExecutorService.isTerminated()) {
sExecutorService = Executors.newFixedThreadPool(3);
}
}
public void recycleChild(HashSet<Integer> idSet,
final View scrapView, int itemId) {
// ����ͼƬ
if (scrapView instanceof ImageView) {
((ImageView) scrapView).setImageResource(0);
// if (front != null && front instanceof BitmapDrawable) {
// BitmapDrawable bitmapDrawable = (BitmapDrawable) front;
// Bitmap bitmap = bitmapDrawable.getBitmap();
// if (bitmap != null && !bitmap.isRecycled()) {
// recycleBitmap(bitmap);
// }
// }
}
Drawable background = scrapView.getBackground();
if (background != null) {
BitmapDrawable bitmapDrawable = null;
if (background instanceof TransitionDrawable) {
background = ((TransitionDrawable) background).getDrawable(1);
}
bitmapDrawable = (BitmapDrawable) background;
final Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && !bitmap.isRecycled()) {
// ����ɹ���childId��Ӽ�����
if (saveBitmap(itemId, scrapView.getId(), bitmap)) {
idSet.add(scrapView.getId());
handler.post(new Runnable() {
@Override
public void run() {
scrapView.setBackgroundResource(0);
}
});
}
}
}
}
public void recycleView(final View item) {
sExecutorService.submit(new Runnable() {
@Override
public void run() {
if (itemStates.get(item.getId(), -1) != -1) {
return;
}
itemStates.put(item.getId(), STATE_RECYCLING);
HashSet<Integer> set = new HashSet<Integer>();
if (item instanceof ViewGroup) {
ViewGroup container = (ViewGroup) item;
for (int i = 0; i < container.getChildCount(); i++) {
View child = container.getChildAt(i);
recycleChild(set, child, item.getId());
}
if (!set.isEmpty()) {
recycleIds.put(item.getId(), set);
}
}
}
});
}
public void reloadView(final View item) {
if (item == null) {
return;
}
final HashSet<Integer> childIds = (HashSet<Integer>) recycleIds
.get(item.getId());
if (childIds == null) {
return;
}
int state = itemStates.get(item.getId()) + 0;
if (state != STATE_RECYCLING) {
return;
}
itemStates.delete(item.getId());
itemStates.put(item.getId(), STATE_RELOADING);
// �Ի����ȡͼƬ
Object[] childIdArray = childIds.toArray();
for (int i = 0; i < childIdArray.length; i++) {
final int childId = (Integer) childIdArray[i];
// �米��Ϊͼ ��Ĭ��Ϊ��һ��
final Bitmap bmp = getBitmapFromMemory(childId + "");
if (bmp != null) {
if (childId == item.getId()) {
// item��ͼ
} else {
// ������ͼ
Log.d(TAG, "�ɹ��Ի����ȡͼƬ" + childId + "--" + item.getId());
View child = item.findViewById(childId);
// ??����
child.setBackgroundDrawable(new BitmapDrawable(bmp));
}
childIds.remove(childId);
} else {
sExecutorService.submit(new Runnable() {
@Override
public void run() {
final Bitmap bmp = getBitmapFromDisk(item.getId());
Log.d(TAG, "�ɹ��Դ��̶�ȡͼƬ" + childId + "--" + item.getId()
+ "---" + bmp);
if (bmp == null)
return;
setBitmapToMemory(item.getId() + "", bmp);
handler.post(new Runnable() {
@Override
public void run() {
if (childId == item.getId()) {
// item��ͼ
} else {
// ������ͼ
View child = item.findViewById(childId);
child.setBackgroundDrawable(new BitmapDrawable(
bmp));
}
childIds.remove(childId);
}
});
}
});
}
}
recycleIds.remove(item.getId());
itemStates.delete(item.getId());
}
/**
* ���ڴ滺���л�ȡbitmap
*
* @param url
* @return bitmap or null.
*/
public static Bitmap getBitmapFromMemory(String key) {
return mLruCache.get(TvUtil.md5(key));
}
/**
* ���ⲿ�ļ������л�ȡbitmap
*
* @param url
* @return
*/
private Bitmap getBitmapFromDisk(int viewId) {
Bitmap bitmap = null;
String fileName = TvUtil.md5(viewId + "");
String filePath = cachedDir + "/" + fileName;
try {
FileInputStream fis = new FileInputStream(filePath);
bitmap = BitmapFactory.decodeStream(fis);
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
bitmap = null;
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
/**
* �洢ͼ����������
*
* @param key
* @param bitmap
*/
public static void setBitmapToMemory(String key, Bitmap bitmap) {
String md5 = TvUtil.md5(key);
if (mLruCache.get(md5) == null) {
mLruCache.put(md5, bitmap);
}
}
public boolean saveBitmap(int itemId, int childId, Bitmap bmp) {
String key = TvUtil.md5(itemId + "");
// ����bitmap���ڴ���������
setBitmapToMemory(key, bmp);
try {
String filePath = this.cachedDir + "/" + key;
FileOutputStream fos = new FileOutputStream(filePath);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
Log.d(TAG, "�ɹ��洢ͼƬ������=" + itemId);
return true;
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* �첽����ͼƬ��ϵĻص��ӿ�
*/
public interface DrawableCallback {
/**
* �ص�����
*
* @param bitmap
* : may be null!
* @param imageUrl
*/
public void onDrawableLoaded(Drawable draw);
}
}