Android 中Handler引起的内存泄露

来源:互联网 发布:玛士达编程用软件 编辑:程序博客网 时间:2024/06/14 17:20

在App代码编程中,我们经常使用Handler进行异步操作,并返回结果。通常我们会这样写:

private final Handler handler = new Handler(){        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            //TODO 数据处理        }    };

但是这样使用是有可能导致内存泄露的,我们可以使用 lint 工具,可以看到 warning(警告),这样书写代码哪里会出现内存泄露呢,在这里我们可以分析一下:
1、Java中非静态内部类和匿名内部类都持有其外部的引用。静态内部类不会持有!

public class ClassTest {      static int a;      int b;       public static void main(String[] args) {          ClassTest oc = new ClassTest();          // new一个外部类          ClassTest oc1 = new ClassTest();          // 通过外部类的对象new一个非静态的内部类          OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();          // 调用非静态内部类的方法          System.out.println(no_static_inner.getKey());      }    具体我们可以参考Java中对非静态内部类的描述与实际的操作流程

2、当一个Android 应用启动的时候,会自动创建一个基于主线程的Looper 实例,在Android中 Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行,这里需要注意的是Looper的生命周期和当前的生命周期一样长!
这里写图片描述
3、当一个Handler主线程进行了初始化之后,我们发送一个对象消息(target)到Handler的Looper的消息队列当中,这个现象实际上就是在发送的消息当中已经包含了Handler实例的引用。只有调用Handler中的回调 handleMessage(Message msg){} 才能完成对消息的处理

最后的解决方式我们可以使用静态内部类,和弱引用的方式解决,个人偏好!示例如下:

/** *@USer wangly */public class MainActivity extends Activity {    private static class MyHandler extends Handler {        private final WeakReference<MainActivity> mActivity;        public MyHandler(MainActivity activity) {            mActivity = new WeakReference<MainActivity>(activity);        }        @Override        public void handleMessage(Message msg) {            MainActivity activity = mActivity.get();            if (activity != null) {                //TODO 相关数据的处理            }        }    }    private final MyHandler mHandler = new MyHandler(this);    private static final Runnable sRunnable = new Runnable() {        @Override        public void run() { /* ... */ }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        // Post a message and delay its execution for 10 minutes.        mHandler.postDelayed(sRunnable, 1000 * 60 * 10);        initView(this);    }    private void initView(MainActivity activity) {    }}
1 0
原创粉丝点击