android handler leaks (内存泄漏)

android handler leaks

内存泄漏概念

内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

问题描述

当我们在activity中做一些异步任务或者延迟任务时很有可能导致内存泄漏,因为如果这些任务没有完成之前我们关闭了activity,按道理无论对用户还是对系统来说正常情况下既然关闭了某个activity活动即不在需要它了那么它也就不必再占用内存空间了。但是当我们使用handler处理任务结果时,那么那些任务必然持有对handler的引用,而handler是activity的成员变量,那么任务未完成之前系统就没法回收被关闭acitivity所所占用的内存空间,这就导致了内存泄漏。
简单来说,就是我们要处理当activity被关闭后能被回收而不占内存空间。

In Android, Handler classes should be static or leaks might occur, Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well.To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.

上面一段说明的最后一句揭示了解决方案,为了防止外部类内存泄漏,就要声明一个对外部类使用弱引用的静态内部类;这里外部类指activity。

自定义一个继承handler的内部类

在activity中自定义一个静态内部类(非静态的会持有外部类的引用),对外部类activity使用弱引用持有。这样就可以对activity回收了。

//demo
static class MyHandler extends Handler{

        WeakReference<Activity> weakReference;

        public MyHandler(Activity activity){
            weakReference = new WeakReference(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 0:
                    if(weakReference != null){
                        Activity activity = weakReference.get();
                        if(activity != null){
                            WebBrowserActivity webBrowserActivity = (WebBrowserActivity) activity;
                            webBrowserActivity.textView.setText("ffff");
                        }
                    }
                    break;
            }
        }
    }

    Handler handler = new MyHandler(this);

测试

可以写MainActivity与SecondActivity两个activity

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.textview).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "start", Toast.LENGTH_SHORT).show();
                startActivity(new Intent(MainActivity.this, WebBrowserActivity.class));
            }
        });
    }
}
SecondActivity.java

public class WebBrowserActivity extends AppCompatActivity {

    static class MyHandler extends Handler{

        WeakReference<Activity> weakReference;

        public MyHandler(Activity activity){
            weakReference = new WeakReference(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 0:
                    if(weakReference != null){
                        Activity activity = weakReference.get();
                        if(activity != null){
                            WebBrowserActivity webBrowserActivity = (WebBrowserActivity) activity;
                            webBrowserActivity.textView.setText("ffff");
                        }
                    }
                    break;
            }
        }
    }

    Handler handler = new MyHandler(this);

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_browser);
        System.out.println(this); // 打印对象地址
        textView = findViewById(R.id.textview);

        handler.sendEmptyMessageDelayed(0, 60000);

        finish();
    }
}

MainActivity只是启动SecondActivity,SecondActivity中用handler发送一条延迟消息后立即finish。

观察heap中的对象

使用AndroidStudio中的AndroidProfiler工具(不会用可百度之)来查看内存中对象。
手动触发GC然后看内存中对象是否被回收了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值