最近看了一些资料,对android的程序的内存有一些想法,我提出来,请大家指正,目的是抛砖引玉。
首先提几个有意思的问题:
1,如果activty destroy掉的话,那么这个activty内的view所引用的bitmap回收掉了吗?
2,如果activty destroy掉的话,那么这个acitity所占用的内存被GC回收了吗?
我觉的一个程序中占用内存的地方有两个方面:一个是bimap。一个是context(activity).
一,先说bitmap:这个引起内存溢出比较普遍。有2个解决方法:
1,用bitmap的recycle方法,在我们确认这个bitmap不被使用的时候调用这个方法可以直接把bitmap所占用的内存回收掉。不过这个方法的使用的弱点是:如果这个方法调用的时间点不合理,很容易引起 use a recycle bitmap的异常。
2,用弱引用来管理你的bitmap。具体方法,是把程序里所有的bitmap对象放到一个静态的hasmap中,用弱引用来保 存。如果再用到这个bitmap的时候,根据相应的key直接取出来,相当于一个高速缓存池。保证这个程序不会重复创建过多的bitmap对象。此外弱引用对象可以在系统内存不足的时候自动被系统回收。
3,设置压缩参数,对bitmap进行压缩。以及用反射设置一下bitmap所占内存的位置(据说可以不算到heap中)。
二, 再说说context: TextView label = new TextView(this); 大家经常这样创建view,这意味着,TextView 拥有对整个Activity的引用以及Activity自身拥有的所有内容;一般是整个的View层次和它的所有资源。因此,如果你“泄露”了Context(“泄露”指你保留了一个引用,阻止了GC的垃圾回收),,你将泄露很多的内存。如果你不够仔细的话,很容易就能泄露一个Activity 。 当一个Drawable附加到一个View上时,View会将其作为一个callback设定到Drawable上。 所以:用activity这个context传到view的setbackground中,其实就把这个acitity “泄漏”了,所以有时候我们destroy掉了这个activity,但是我们用内存分析工具查看内存的时候,奇怪的发现这个activity并没有没gc回收掉。要避免这个问题有两个解决方法:
1,不用activity的context 而是用application的context,这样acitity可以适时的被系统回收掉。
2,在acitity destroy 方法中 解除activity和biamap(drawble) 的绑定关系。去除bitmap对activity 引用的保留,让系统适时的去回收。
具体代码为
@Override
protected
void
onDestroy() {
super
.onDestroy();
unbindDrawables(findViewById(R.id.RootView));
//
System.gc();
}
private
void
unbindDrawables(View view) {
if
(view.getBackground() !=
null
) {
view.getBackground().setCallback(
null
);
}
if
(view
instanceof
ViewGroup) {
for
(
int
i =
0
; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
说了这么多哈哈,你觉的我说的对不?
参考资料:http://developer.android.com/resources/articles/avoiding-memory-leaks.html
http://www.alonsoruibal.com/bitmap-size-exceeds-vm-budget/