Android- Handler更新UI避免内存泄露的三种写法比较

本文探讨了Android中Handler可能导致内存泄漏的问题,分析了匿名内部类、静态内部类以及弱引用在Handler使用中的区别。通过三种不同的Handler写法,揭示了内存泄漏的原理,并提出了解决方案,特别强调了静态内部类结合弱引用的方式可以有效防止内存泄漏。同时,文章在实际代码示例中展示了如何避免延迟消息导致的内存泄漏。
摘要由CSDN通过智能技术生成

最近,换了公司。新公司的项目,估计很古老了。发现很多模块的Handler写法都是很古老的,没有经过优化的写法,编译器一大块(可能造成内存泄露)黄色警告。虽然工作多年,对Handler的使用优化,基本上也是参考网上的代码,使用静态匿名内部类+弱引用处理,使编译器不再警告即可。如今再碰到这样的问题,就准备稍微总结一下。不总结不知道,一总结,发现这里面还是存在一些,我无法完全解释的问题。

package com.test.util.ori_code;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import com.common.base.BaseFragment;
import com.common.utils.LogUtil;
import com.test.util.R;

import java.lang.ref.WeakReference;
import java.util.concurrent.Executors;

/**
 * Handler验证
 */
public class Fragment_01 extends BaseFragment {

    private TextView textInfo;

    @Override
    protected int getLayoutId() {
        return R.layout.ori_code_fragment_1;
    }


    /**
     * /写法1: 匿名内部类写法 (编译器有内存泄露警告)
     * 此时即使把 handler1 设为static也依然会有内存泄露警告(问题? 既然设置为static 并且编译通过,
     * 那么匿名内部类对象Handler1是不会依赖外部对象的,
     * 因为静态成员初始化优先于对象,为什么还会有内存泄露警告?是编译器警告的bug?)
     */
    private Handler handler1 = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String text = "handler1收到了信息: what:" + msg.what;
            LogUtil.d(text + " this:" + textInfo);
            textInfo.setText(text);
        }
    };


    /**
     * 写法2:(编译器无内存泄露警告) handler1 handler2 的区别是什么, 为什么写法2是正常的,没有内存泄露警告?
     * handle之所以会内存泄露 是因为如果不主动销毁,其正常的生命周期会比外部类长,而其如果持有外部类对象,
     * 会导致外部类对象不能及时回收。此种写法,直接持有外部类对象的是Handler.Callback,而非handler2??
     */
    private Handler handler2 = new Handler(new Handler.Callback() {
        @SuppressLint("SetTextI18n")
        @Override
        public boolean handleMessage(Message msg) {
            String text = "handler2收到了信息: what:" + msg.what;
            LogUtil.d(text + " this:" + textInfo);
            textInfo.setText(text);
            return false;
        }
    });

    /**
     * 写法3:静态内部类写法(编译器无警告,静态内部类不依赖外部类的对象)
     */
    private static class MyHandle extends Handler {
        WeakReference<Fragment_01> weakReference;

        public MyHandle(Fragment_01 fragment_01) {
            this.weakReference = new WeakReference<>(fragment_01);
        }

        @SuppressLint("SetTextI18n")
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String text = "handler3收到了信息: what:" + msg.what;

            Fragment_01 fragment_01 = weakReference.get();
            LogUtil.d(text + " this:" + fragment_01);
            if (fragment_01 != null) {
                fragment_01.textInfo.setText(text);
            }
        }
    }

    @Override
    protected void initView() {
        textInfo = findViewById(R.id.text_info);
        Executors.newSingleThreadExecutor().execute(() -> {
            //即时消息测试
            findViewById(R.id.btn_1).setOnClickListener(v -> handler1.sendEmptyMessage(1));
            findViewById(R.id.btn_2).setOnClickListener(v -> handler2.sendEmptyMessage(2));
            findViewById(R.id.btn_3).setOnClickListener(v -> new MyHandle(this).sendEmptyMessage(3));

            //延迟消息测试 内存泄露问题
            findViewById(R.id.btn_1_test).setOnClickListener(v -> handler1.sendEmptyMessageDelayed(11, 3000));
            findViewById(R.id.btn_2_test).setOnClickListener(v -> handler2.sendEmptyMessageDelayed(22, 3000));
            findViewById(R.id.btn_3_test).setOnClickListener(v -> new MyHandle(this).sendEmptyMessageDelayed(33, 3000));
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        handler2.removeCallbacksAndMessages(null);
        LogUtil.d("========onDestroy=============");
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值