zoukankan      html  css  js  c++  java
  • 什么导致了Context泄露:Handler&内部类

    参考:http://www.cnblogs.com/kissazi2/p/4121852.html

    为什么 内部自定义handler类要static类型?

    原因:

    1、当一个Android应用程序第一次启动时,Android框架为应用程序的主线程创建一个Looper对象。一个Looper实现了一个简单的消息队列,在一个循环中处理Message对象。所有主要的应用程序框架事件(如活动生命周期方法调用,单击按钮,等等)都包含在Message对象,它被添加到Looper的消息队列然后一个个被处理。主线程的Looper在应用程序的整个生命周期中存在。

    2、当一个Handle在主线程被实例化,它就被关联到Looper的消息队列。被发送到消息队列的消息会持有一个Handler的引用,以便Android框架可以在Looper最终处理这个消息的时候,调用Handler#handleMessage(Message)
    3、在Java中,非静态的内部类和匿名类会隐式地持有一个他们外部类的引用。静态内部类则不会

    解释:handler中的消息持有handler的引用,handler又是个匿名内部类持有activity的对象.如果msg是个延时操作那么当actvity finish的时候,act的引用被持有,造成 activity中的对象都不会释放 造成内存泄露.

    正确的代码:

    1.handler 和 runable方法都声明static 即 凡是在handler中使用的内部类(不能使用匿名类) 都要声明为static 类型

    2.handler中要持有 activity或者 context对象需要使用 弱引用

    public class SampleActivity extends Activity {
        /**
        * 匿名类的静态实例不会隐式持有他们外部类的引用
        */
        private static final Runnable sRunnable = new Runnable() {
                @Override
                public void run() {
                }
            };
    
        private final MyHandler mHandler = new MyHandler(this);
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // 延时10分钟发送一个消息.
            mHandler.postDelayed(sRunnable, 60 * 10 * 1000);
    
            // 返回前一个Activity
            finish();
        }
    
        /**
        * 静态内部类的实例不会隐式持有他们外部类的引用。
        */
        private static class MyHandler extends Handler {
            private final WeakReference<SampleActivity> mActivity;
    
            public MyHandler(SampleActivity activity) {
                mActivity = new WeakReference<SampleActivity>(activity);
            }
    
            @Override
            public void handleMessage(Message msg) {
                SampleActivity activity = mActivity.get();
    
                if (activity != null) {
                    // ...
                }
            }
        }
    }
  • 相关阅读:
    Swift中字符串转化为Class的方法
    React Native安装
    关于error:Cannot assign to 'self' outside of a method in the init family
    Xcode6中Swift没有智能提示和自动补全功能
    关于消息推送的补充,主要介绍服务端的实现,包含object c 版本 c 版本 java 版本 php 版本 (转)
    Git和GitHub在线学习资源整理(转)
    HTTP协议详解(转)
    iOS开发之GCD基础
    一步一步实现消息推送 2014-06-19
    理解Certificate、App Id、Identifiers 和 Provisioning Profile
  • 原文地址:https://www.cnblogs.com/wjw334/p/4488427.html
Copyright © 2011-2022 走看看