android内存泄露:3、Handler的错误使用导致内存泄露

目录

一、前言

二、Handler的错误使用导致内存泄露

案例:写一个计时器

1、新建一个 Module,写主界面 MainActivity,布局 activity_main

2、写业务逻辑

3、效果展示

4、解决方案


一、前言

上篇文章我们介绍了:非静态的内部类错误使用_情形二,在Activity中,使用单例工厂类引用 Activity内部类。详细可参考博文:原创 android内存泄露:2、非静态的内部类错误使用_情形二 ,这篇文章我们将介绍:Handler的错误使用导致内存泄露

二、Handler的错误使用导致内存泄露

案例:写一个计时器

1、新建一个 Module,写主界面 MainActivity,布局 activity_main

MainActivity

public class MainActivity extends AppCompatActivity {

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

    public void handlerUse(View view) {
        startActivity(new Intent(MainActivity.this, HandlerActivity.class));
    }

}

activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:text="Handler的错误使用"
        android:onClick="handlerUse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

 

2、写业务逻辑

HandlerActivity

public class HandlerActivity extends AppCompatActivity {

    private TextView mTextView;
    private Handler mHandler = new Handler();

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

        mTextView = (TextView) findViewById(R.id.tv_time);

        //1秒之后执行一次以下方法
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //获取当前时间设置为View
                String time = getStringTime();
                mTextView.setText(time);

                //这里的this代表这实现了Runnable接口的匿名内部类对象
                //使得其每隔1秒都会执行该方法
                mHandler.postDelayed(this, 1000);

            }
        }, 1000);

    }


    /**
     * 获取系统时间并格式化
     * @return
     */
    private String getStringTime() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(new Date());
    }


}

 

3、效果展示

类似上两篇文章,使用 LeakCanary工具,会测试到内存泄露的相关信息,这里就不截图和录视频了。

 

4、解决方案

/**
 * 我们使用Handler发送了循环任务,即:在一个任务执行完前再发送一个同样的任务。这样任务就永远也执行不完。
 *
 * 我们使用Handler发送了Runnable任务,该Runnable任务是一个匿名内部类,对外部类有隐式的强引用,
 * 也就是Runnable对象引用到了Activity,同时Runnable被发送到了MessageQueue中,也就是MessageQueue引用到了Runnable,
 * MessageQueue属于Looper对象的成员变量,因此MessageQueue又被Looper对象引用到,
 * Looper对象是在Looper.prepare()阶段创建并绑定到主线程的
 */

解决方式:当 HandlerActivity销毁的时候,移除当前 mHandler发送的所有的msg消息和任务

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //移除当前 mHandler发送的所有的msg消息和任务
        mHandler.removeCallbacksAndMessages(null);
    }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

被开发耽误的大厨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值