Android中要小心的一种内存泄露
今天把android-developers blog上的一些文章看了下,有篇文章《avoiding memory leaks》虽然以前也扫了眼,今天再看了一遍,觉得好bt啊。
private static Drawable sBackground; @Override protected void onCreate(Bundle state) { super.onCreate(state); TextView label = new TextView(this); label.setText("Leaks are bad"); if (sBackground == null) { sBackground = getDrawable(R.drawable.large_bitmap); } label.setBackgroundDrawable(sBackground); setContentView(label); }
这段代码看得出会内存泄露么?按文中解释说,因为setbackgrounddrawable时,会在drawable中把label这个textview设为callback,就是说drawable中对label有引用,而label中对当前activity的context也有引用。所以当转屏时,系统自动重新建立ui时,原有的整个activity都不能被回收。
作为一个普通的java程序员,真的能想到这个么?文档里也没有提示过,没看到这篇文章,又没自己去看drawable的源代码的开发者,怎么能猜到这个。至少在我第一印象中,我是觉得drawable对象只是类似于image的一类对象。系统竟然在我不注意的时候自动设置了callback。唉,我得检查检查自己的代码中有没有这样的问题了。我不知道除了这个drawable外,还有没有其它类似的东西,真是防不胜防啊
03-15增: 不过我想了下,好像也有点不对啊
当第二次重设label.setbackgrounddrawable(sbackground);时,应该是把sbackground的
callback改回成当前的label啦。那这时gc不就应该能工作么
感觉框架没设计好啊这是,UI里面这类问题是Java主要memory leak来源之一…如果Android支持WeakReference, sBackground对label的引用用WeakReference可能比较合适…
你后面说那个,关键是如果sBackground一直是不会回收的,那么这样它就永远hold着一个没用的Activity,这可能是很大的一笔内存…
[Reply]