Android 内存泄露的几种情形

来源:互联网 时间:1970-01-01

内存泄露的定义

       根据百度百科的定义:内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄露,在Android里就是 该回收的资源没有被GC(垃圾回收机制)回收,因为界面(Activity)在android中占比很大,所以Activity的内存泄露很常见。又由于Activity中加入了对各种资源的引用,特别是图片资源,所以Activity的回收意义重大。

由于单例中保有Activity对象

当某一个单例中需要使用Context作为参数的时候,我们常常在界面中将Activity.this传入到单例中。

       

package com.example.memoryleak;import android.content.Context;public class AppManager { private static AppManager appManager; private static Context context; private AppManager() { appManager = new AppManager(); } public static AppManager getInstance(Context context) { AppManager.context = context; if(appManager==null) { appManager = new AppManager(); } return appManager; } }
这样代码看似没有问题,但是当你在界面中调用finish()方法以后,你的Activity不能及时的回收。

原因:

       AppManager对象是static类型的,这就注定这个对象的生命周期比很多的Activity生命周期都要长很多,在Activity被关闭以后,垃圾回收器视图回收这块内存区域,但是AppManager保有此界面的引用,这样GC就无法完成回收,造成此界面常驻内存,引发内存泄露。

解决办法:

1,针对参数不必是Activity的:在单例中不要传入Activity,可以用Application.getContext()作为参数。因为Application类的生命周期伴随整个应用的启动和关闭,单例的生命周期和Application大致相同。2,针对必须传入Activity做参数的:把activity作为方法内部变量使用,因为当此方法执行完以后,方法内部的变量就会被释放。这样单例就不会保有界面的引用,从而避免内存泄露。

由于使用Handler导致的内存泄露

<span style="font-size:18px;">package com.example.memoryleak;import android.app.Activity;import android.os.Bundle;import android.os.Handler;/** * 内存泄露的几种情形 * @author yuanyang * */public class MainActivity extends Activity { private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }</span>


在使用Handler+Message模型的时候。Eclispe会提示我们

- This Handler class should be static or leaks might occur (com.example.memoryleak.MainActivity.1)。eclipse提示我们:handler要定义成static,不然会出现内存泄露。

原因:

由于handler+message的实现机制,handler.sendMessage(msg)将Message对象送入到消息队列中,消息队列是在应用创建的时候生成,在应用退出的时候销毁。此时消息队列可能很繁忙,造成当前消息不能及时处理,而Handler得handleMessage方法得不到及时运行,这样handler对象的引用始终在消息队列里面,导致Handler不能被回收,而保有该handler得Activity就不能就是得到回收,造成内存泄露。

解决方法:

将Handler定义成static类型的。因为static类型的变量不属于任何特定的类,这样在Activity回收的时候就不会因为Handler而得不到及时回收。以上是我对安卓内存泄露的拙见,有意见的可以留言


相关阅读:
Top