Android打开一张图片关闭,打开,再关闭,OOM了,GC也没用,发现是界面的图片资源没用释放掉;
GirdView和ListView可以自动回收子View但是如果自己动态加载图片的布局不合理,android就不会回收Bitmap;
可以使用 SoftReference软引用,也可以像下面这样复杂的方法回收自己的图片布局,图片控件会变白闪烁一下.
Android的OOM除了本身图片过大会OOM,需要进行bitmap.option或者thumb压缩以外(ps:google的压缩方法对图片高宽反着的图片是会崩溃的);
对于每个界面中的ImageView占用的Bitmap是要回收的.今天先发个回收界面中ImageView中图片的.
对于每个Activity来说,
只要在父Activity上使用Map recycleViews;
在动态创建的View上回收该View中的
ImageView;recycleViews.put(gridView, new int[]{R.id.iv_item_chooseimg_big,R.id.iv_item_chooseimg_small});
在合适的地方,比如返回的时候,处理这个对象就行了;
RecycleBitmap.recycle(recycleViews);
* @author intbird 20140225
*/
package core.tool;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ImageView;
public class RecycleBitmap {
/**
* 清理map中的bitmap;
* @param imgCache ImageCacheMap
* @param maxSize 允许添加的最大图片数量
* @param freeSize 释放掉图片的数量;
*/
public static void recycleMapCache(LinkedHashMap<String, Bitmap> imgCache,int maxSize,int freeSize){
//超出最大容量时清理
if (imgCache.values().size() > maxSize) {
synchronized(imgCache){
Iterator<String> it = imgCache.keySet().iterator();
while( it.hasNext()&&(imgCache.keySet().size()>freeSize)){
Bitmap bmp=imgCache.get(it.next());
if(bmp!=null&&!bmp.isRecycled()) {
bmp.recycle();
bmp=null;
}
it.remove();
}
}
System.gc();
}
}
/**
* 清理View中的ImagView被BitMap占用的内存;
* @param mapViews 一个View的合集
*/
public static void recycle(Map<View,int[]> mapViews){
synchronized(mapViews){
Iterator<View> it = mapViews.keySet().iterator();
while(it.hasNext()){
//获取布局
View view=it.next();
if(view==null) return;
//获取要布局内要回收的ids;
int [] recycleIds=mapViews.get(view);
//如果是listView,先找到每个布局文件.重要提示:每个ImagView在布局文件的第一层;
if ((view instanceof AbsListView)) {
recycleAbsList((AbsListView)view, recycleIds);
}
//如果是ImageView,直接回收;
else if(view instanceof ImageView){
recycleImageView(view);
}
//如果是ViewGroup,重要提示:每个ImagView在ViewGroup的第二层;
else if ((view instanceof ViewGroup)) {
recycleViewGroup((ViewGroup)view, recycleIds);
}
}
}
System.gc();
}
/**
* 回收继承自AbsListView的类,如GridView,ListView等
* @param absView
* @param recycleIds 要清理的Id的集合;
*/
public static void recycleAbsList(AbsListView absView,int[]recycleIds){
if(absView==null) return;
synchronized(absView){
//回收当前显示的区域
for (int index = absView.getFirstVisiblePosition(); index <= absView.getLastVisiblePosition(); index++) {
//获取每一个显示区域的具体ItemView
ViewGroup views = (ViewGroup) absView.getAdapter().getView(index, null, absView);
for(int count=0;count<recycleIds.length;count++){
recycleImageView(views.findViewById(recycleIds[count]));
}
}
}
}
/**
* 回收继承自AbsListView的类,如GridView,ListView等
* @param absView
* @param recycleIds 要清理的Id的集合;
*/
public static void recycleViewGroup(ViewGroup layout,int[]recycleIds){
if(layout==null) return;
synchronized(layout){
for (int i = 0; i < layout.getChildCount(); i++) {
View subView = layout.getChildAt(i);
if (subView instanceof ViewGroup) {
for(int count=0;count<recycleIds.length;count++){
recycleImageView(subView.findViewById(recycleIds[count]));
}
} else {
if (subView instanceof ImageView) {
recycleImageView((ImageView)subView);
}
}
}
}
}
/**
* 回收ImageView占用的图像内存;
* @param view
*/
public static void recycleImageView(View view){
if(view==null) return;
if(view instanceof ImageView){
Drawable drawable=((ImageView) view).getDrawable();
if(drawable instanceof BitmapDrawable){
Bitmap bmp = ((BitmapDrawable)drawable).getBitmap();
if (bmp != null && !bmp.isRecycled()){
((ImageView) view).setImageBitmap(null);
bmp.recycle();
bmp=null;
}
}
}
}
}
网友评论