常见内存泄漏
原因:一般问题在于存在 ”工作线程实例 持有外部类引用“ 的引用关系和工作线程实例的生命周期 > 外部类的生命周期
1.集合使用完没有清空和=null
2.staitc成员变量的引用使用context
解决方法:
1.使用applicationContext
2.用弱引用
3.非静态内部类的实例是静态
public class Human {
private static int age = 1;// 年龄
private String name;// 姓名
private static Man whiteMan;// 白人
// 内部类
public class Man{}
public void setWoMan(WoMan woMan){}
public void test(){
Human human = new Human();
// 向human对象setMan方法中传入一个匿名的Man对象
human.setMan(new Man()); //没问题
whiteMan = new Man(); //非静态内部类的实例是静态,泄露
}
}
whiteMan是持有持有外部类Human的隐式引用,但是whiteMan是static的,static修饰的变量是放在内存中,生命周期是超过Human的,此时发生内存泄漏
解决方法:
1.改成静态内部类
public staitc class Man{}
2.将内部类变成一个单例
4.AsyncTask、实现Runnable接口、继承Thread类、Handler
背景:
- Android的Looper和Handler的一个过程:当Android application 启动之后,framework会创建一个Looper对象,接着Looper实现一个简单的消息队列,在一个消息循环中处理Message对象。主线程Looper存在于整个App的生命周期。
- 在主线程中实例化Handler之后,它关联了Looper的消息队列,消息队列里面的Message对象会持有Handler的引用。这样是为了Hander能调用handler的handleMessage()方法去处理这个Message对象
- 非静态的内部类和匿名类会隐式地持有一个他们外部类的引用。静态内部类则不会。
public class SampleActivity extends Activity {
private final Handler mLeakHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
}
解决方法:
1.静态内部类+弱引用
2.当外部类结束生命周期时,清空Handler内消息队列/强制结束线程
handler.removeCallbacksAndMessages(null)
5.广播BraodcastReceiver、文件流File、数据库游标Cursor、图片资源Bitmap等
解决方法:
1.在Activity销毁时 及时关闭 / 注销资源
2.final中关闭
3.软引用
可以用java最新语法
try(File jar = new File(source)) {
} catch (Exception e) {
}
6.adapter没有使用ConvertView缓存或使用viewholder
Q:这里ViewHolder静态类结合缓存convertView与直接使用convertView有什么区别吗,是否重复了?
A:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById(),只需要直接setData
参考:
https://blog.csdn.net/u010618194/article/details/64147538
https://www.cnblogs.com/loulijun/archive/2012/04/10/2437888.html
https://blog.csdn.net/Zheng548/article/details/62418032
https://cloud.tencent.com/developer/article/1179625