View是如何导致内存泄露的

View对象为我们在屏幕显示界面上,它帮助我们更新界面和信息。但是我们却很少想到,他们是很占用内存的。如果View导致了内存泄露也会出现大问题。

Android中的gc只会回收内存中不被任何对象引用到的对象。内存泄露则是内存中不再需要的对象却被其他对象引用,导致对象无法被回收。

View内部保存这对其Activity的引用,如果View内存泄露了,那么整个Activity与其中的数据都不会被gc回收。这个没被回收的Activity占用大量的内存就会导致很大的内存问题。

想象一下,你的Activity设置为可旋转的。当你旋转你的手机,当前Acivity会被Destory然后系统会创建新的Activity实例。如果View内存泄露了,当前Activity就无法被回收,但是新的实例还是被创建了。现在你的内存中就会有两个当前Activity的实例存在。然后你又旋转回去,新的Activity实例还是无法回收,而又创建了新的实例。糟糕,现在内存中有3个当前Activity的实例了。这就造成了巨大的内存泄露问题。

如何避免View内存泄露

不要在异步任务回调中引用View

//some activity code
void onClick(final View view){
	webservice.fetchPosts(new Callback(){
	    public void onResult(Response response){
	        //The View may not be valid and the Activity may be gone
	        view.yoPerfSoSlow();
	    }
	});
}

上面的代码中,在webservice的异步回调中引用到了View。当异步任务执行完成之前,Activity需要Destory,但是由于异步任务的引用导致Activity无法被杀死。更糟糕的是,Activity只有在异步任务被释放后才能被杀死。

那么我们应该怎么在异步任务回调后更新View呢?

我们可以利用Android的LocalBroadcastManager发送本地广播让Activity更新View或使用Otto库。

不要在静态对象中引用View

如上图所示,静态对象的生命周期和App一样长。直到应用退出才会被回收。被静态对象引用的View在整个应用生命周期中都不会被销毁,其引用的Activity也不会被销毁,直到应用退出。

不要将View放到没有clear memory patterns的集合中(抱歉我不知道怎么翻译:p)

我们可以将View作为值放入到WeakHashMap中,它将View作为强引用进行存储。但是在内存回收时,若View没有引用依然能够被回收(这里WeakHashMap没有被回收)。


IMAKIBA

Welcom to my blog!