声明:内容仅限个人笔记,无参考学习价值
Handler内存泄漏及其解决方法:
1.非静态内部类,匿名内部类,都默认持有外部类的引用, 而静态内部类就不持有外部类的引用
2.Looper对象会伴随整个应用的生命周期
3.弱引用的对象拥有短暂的生命周期。在垃圾回收器线程扫描时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存
4.Message对象持有Handler的对象,而Handler持有Activity的对象
msg.target,就是Message持有Handler的对象
未被处理 / 正处理的消息 -> Handler实例 -> 外部类” 的引用关系
两种解决方案:
1.在外部类onDestory()中调用Handler的removeCallbacksAndMessages(null)
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
// 外部类Activity生命周期结束时,同时清空消息队列 & 结束Handler生命周期
}
2.使用static内部类和弱引用
public class OutActivity {
InnerClass innerClass = new InnerClass(this)
static class InnerClass extends Handler {
private WeakReference<Activity> reference;
public InnerClass(OutActivity activity ) {
reference = new WeakReference<Activity>(activity);
}
@override
public void handleMessage(Message msg) {
.......执行操作,调用activity中得数据
}
}
}
还有可能存在内存泄漏的一些地方:
1.单例模式
2.线程泄漏
3 Static 关键字修饰的成员变量
static修饰后,此成员变量的生命周期和应用程序的生命周期相等,被他引用的对象,无法得到释放,变回引起内存泄漏
public class LeakDemo {
private static Context mContext;
public void setContext(Context context) {
this.mContext = context;
}
}
static成员变量导致的memoryLeak.png
4.各类资源未及时关闭
以下内容原文链接: https://blog.csdn.net/printfcc/article/details/79131479
关于一些内存泄漏的建议
- 对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
- 对于生命周期比Activity长的对象如果需要应该使用ApplicationContext
-
在涉及到Context时先考虑ApplicationContext,当然它并不是万能的,对于有些地方则必须使用Activity的Context,对于Application,Service,Activity三者的Context的应用场景如下:
这里写图片描述
其中:NO1表示Application和Service可以启动一个Activity,不过需要创建一个新的task任务队列。而对于Dialog而言,只有在Activity中才能创建
对于需要在静态内部类中使用非静态外部成员变量(如:Context、View ),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏
对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
a.将内部类改为静态内部类 b.静态内部类中使用弱引用来引用外部类的成员变量
对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null
保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期
其他需要知道的引用
在JDK1.2,Java就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
强引用
强引用是最常用的引用,比如我们常常需要的创建对象
String s = new String("帅哥");
1
特点:GC不会回收它,就算内存吃紧也打死不回收
软引用
软引用用来描述一些还有用但是并非必须的对象,对于软引用关联着的对象,只有在内存不足的时候GC才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。
HappyClass happy = new HappyClass ();
SoftReference aSoftRef=new SoftReference(happy);
HappyClass happy =(HappyClass)aSoftRef.get();
1
2
3
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
ReferenceQueue queue = new ReferenceQueue();
SoftReference ref=new SoftReference(aMyObject, queue);
1
2
虚引用
“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
————————————————
网友评论