Android App 内存泄露之Handler

来源:互联网 发布:ipad自带录屏软件 编辑:程序博客网 时间:2024/06/01 10:26

一:为啥出现这样的问题呢

1.在Java中,非静态(匿名)内部类会默认隐性引用外部类对象。而静态内部类不会引用外部类对象。 如果外部类是Activity,则会引起Activity泄露 。当Activity finish后,延时消息会继续存在主线程消息队列中1分钟,然后处理消息。而该消息引用了Activity的Handler对象,然后这个Handler又引用了这个Activity。这些引用对象会保持到该消息被处理完,这样就导致该Activity对象无法被回收,从而导致了上面说的 Activity泄露。
2.Handler 的生命周期与Activity 不一致当Android应用启动的时候,会先创建一个UI主线程的Looper对象,Looper实现了一个简单的消息队列,一个一个的处理里面的Message对象。主线程Looper对象在整个应用生命周期中存在。当在主线程中初始化Handler时,该Handler和Looper的消息队列关联(没有关联会报错的)。发送到消息队列的Message会引用发送该消息的Handler对象,这样系统可以调用 Handler#handleMessage(Message) 来分发处理该消息。handler 引用 Activity 阻止了GC对Acivity的回收

二、内存泄露的危害

  内存泄露的危害就是会使虚拟机占用内存过高,导致OOM(内存溢出),程序出错。

  对于Android应用来说,就是你的用户打开一个Activity,使用完之后关闭它,内存泄露;又打开,又关闭,又泄露;几次之后,程序占用内存超过系统限制。

三:如何避免修

1.静态内部类。将Handler声明为静态类。
PS:在Java 中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用,静态的内部类不会持有外部类的引用。

2.使用弱引用 WeakReference
静态类不持有外部类的对象,所以你的Activity可以随意被回收。由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你需要在Handler中增加一个对Activity的弱引用(WeakReference)。

**   *    * 实现的主要功能。   *    * @version 1.0.0   * */  public class HandlerActivity extends Activity {        private final Handler mHandler = new MyHandler(this);      @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          mHandler.sendMessageDelayed(Message.obtain(), 60000);      }      public void todo() {              };      private static class MyHandler extends Handler {          private final WeakReference<HandlerActivity> mActivity;          public MyHandler(HandlerActivity activity) {              mActivity = new WeakReference<HandlerActivity>(activity);          }          @Override          public void handleMessage(Message msg) {              System.out.println(msg);              if (mActivity.get() == null) {                  return;              }              mActivity.get().todo();          }      }  
1 0
原创粉丝点击