内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

安卓中常见的容易导致内存泄露的原因有以下几种:

1.非静态内部类的使用;

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyAdapter extends FragmentPagerAdapter{

public MyAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {
return null;
}

@Override
public int getCount() {
return 0;
}
}

以上的例子使我们在开发中常用的使用内部类,但是这样写会导致内部类一直持有外部类(Activity等)的引用,所以如果当activity退出时, 此内部类依然持有按错activity 的引用,导致activity无法回收,则会导致activity的内存泄漏。

2.非静态handler的使用:

eg:

1
2
3
4
5
6
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};

以上是我们常见的handler 的构造,as也会提示我们会有内存泄露的问题。原因呢?建议去过一遍Handler的源码,回调的handlerMessage方法中的message对象有个target属性指向的就是当前的Handler,所以如果存在message,那么因为它持有了Handler对象,而Handler对象又是当前类的匿名内部类,持有当前类的引用,导致当前类无法释放,从而造成了内存泄漏。

3.eventBus未取消注册

4.Rxbus未取消注册

5.广播为取消注册

以上三种情况类似,这里就不过多介绍。

6.不规范的单例导致的内存泄漏:

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Utils {
private Context context;
private static Utils utils;

private Utils(Context context) {
this.context = context;
}

public static Utils getInstance(Context context) {
if (utils == null) {
synchronized (Utils.class) {
if (utils == null) {
utils = new Utils(context);
}
}
}
return utils;
}

}

以上的单例模式每次在使用的时候会传入一个Context对象,因为单利对象是一直存在的,使用完并不会被释放,所有导致持有的context不会被释放,context一般是Activity,所以就导致了Activity的内存泄漏。正确的写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Utils {
private Context context;
private static Utils utils;

private Utils(Context context) {
this.context = context;
}

public static Utils getInstance(Context context) {
if (utils == null) {
synchronized (Utils.class) {
if (utils == null) {
utils = new Utils(context.getApplicationContext());
}
}
}
return utils;
}

本文地址: http://www.yppcat.top/2019/03/20/安卓内存泄漏/