Android内存泄露之非静态内部类|匿名内部类

原文:https://blog.csdn.net/u012982629/article/details/82770282

知识点:

非静态内部类|匿名内部类 默认持有外部类的引用

什么是内存泄露?
Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收;另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收。

首先我们储备一个知识点
在Java中非静态内部类 | 匿名内部类都默认持有外部类的引用,使用不当的话会使外部类一直被某对象持有引用,从而在其该被GC回收时却不被回收,也最终导致了内存泄漏。

我们经常用到的AsyncTask、Runnable、Handler、Thread等类,在采用非静态内部类|匿名内部类的方式使用的话,都会隐式地持有外部类的引用。
其原因其实也好理解的,如果不是隐式地持有外部类的引用,我们怎么可以在内部任意使用外部类的变量、方法呢?

出现内存泄漏的原因大都是在Activity已经销毁的时候,其还有在执行未关闭的后台线程或MessageQueue(消息队列)中有延时待分发处理的Message,Message中又持有Handler实例,Handler又持有Activity实例。

解决方案有2个思路:

  • 严格保证程序逻辑
  1. 在销毁Activity的时候结束掉在执行的后台线程。线程结束了,就等于切断了与外部类关联的线。
  2. 使用Handler.postDelayed( new Runnable(),xxx)方式的话,直接调用Handler的removeCallbacksAndMessages(null)方法,移除回收消息队列的消息即可。
  • 采用静态内部类+弱引用(WeakReference)持有外部类实例
private  static class MyHandler extends Handler {
   WeakReference<Activity > mActivityReference;

   MyHandler(Activity activity) {
       mActivityReference= new WeakReference<Activity>(activity);
   }

   @Override
   public void handleMessage(Message msg) {
       final Activity activity = mActivityReference.get();
       if (activity != null) {
          activity.xxx ......;
       }
   }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章