内存泄露问题可以分为以下几种情况:
1. 静态变量引起的泄露
2. 非静态内部类引起的内存泄漏
3. 资源关闭引起的内存泄露
首先是静态变量引起的泄露:
Android的生命周期是在进程启动时开始,在进程死亡时结束。所以在程序的运行期间,如果进程没被杀死,那么静态变量会一直存在,不会回收掉。假如静态变量强引用了某个Activity,那么这个Activity即使执行了ondestroy()方法也不会被回收。
这类问题的解决方案为:
1、寻找与该静态变量差不多生命周期的对象替代
2、若找不到将强引用改为弱引用
典型的例子单例引起的context的泄露
public class MyHelper {
private static MyHelper helper = null;
private Context context;
private MyHelper(Context context) {
this.context = context;
}
public static MyHelper synchronized getInstance(Context context) {
if (helper == null) {
helper = new MyHelper(context);
}
return helper;
}
}
当执行getInstance方法传入的context为Activity时,只要该单例没有被释放那么该Activity就不会被释放。
解决方案:传入Application的Context,因为Application的Context的生命周期要比Activity的时间长,可以理解改context和单例的生命周期一样长。
public class MyHelper {
private static MyHelper helper = null;
private Context context;
private MyHelper(Context context) {
this.context = context;
}
public static MyHelper synchronized getInstance(Context context) {
if (helper == null) {
helper = new MyHelper(context.getApplicationContext());
}
return helper;
}
}
非静态内部类引起的内存泄漏:
在Java中,创建非静态内部类实例,会引用外部类。如果这个非静态内部类做了耗时操作,会引起该外部类不会被回收造成内存泄露。
这类问题的解决方案是:1、将非静态内部类变为静态内部类2、如果有强引用Activity改为若引用3、在业务允许的情况下,在当Activity执行ondestroy()时释放掉这些耗时操作。
handler引起的内存泄露解决:
public class MyActivity extends Activity {
private Myhandler myhandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myhandler = new Myhandler(this);
}
// 将handler改为静态匿名类
private static class Myhandler extends Handler {
private WeakReference<MyActivity> weakReference = null;
public Myhandler(MyActivity activity) {
// 将需要引用的Activity变为弱引用
weakReference = new WeakReference<MyActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MyActivity aty = weakReference == null ? null : weakReference.get();
// 如果Activity被释放回收,则不处理数据
if (aty == null || aty.isFinishing()) {
return;
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// Activity退出时取消回调
myhandler.removeCallbacksAndMessages(null);
}
}
在就是资源未关闭引起的内存泄露:
当使用BraodcastReceiver,cursor,Bitmap等资源时,需要及时释放掉,若没有释放则会引起内存泄露。