【Android开发】 Handler做消息发送与异步处理遇到的坑

Handler class should be static or leaks might occur

在Android线程通信中,常用的方法就是创建一个Message(android.os.Message) 对象,并将它的what字段指定对应值,调用HandlersendMessage() 方法将这个Message发送出去。代码如下

  val handler = object : Handler() {

        val TEST = 1

        override fun handleMessage(msg: Message) {
            when (msg.what) {
                TEST -> {
                    TODO()
                }
            }
        }
    }

大部分的教材都会使用这个方法,但是在编程中,我们会发现这样的代码会存在几个问题

  1. Handler class should be static or leaks might occur

This Handler class should be static or leaks might occur (anonymous android.os.Handler)

这是因为Handler在Android中用于消息的发送与异步处理,常常在Activity中作为一个匿名内部类来定义,此时Handler会隐式地持有一个外部类对象(通常是一个Activity)的引用。当Activity已经被用户关闭时,由于Handler持有Activity的引用造成Activity无法被GC回收,这样容易造成内存泄露。

解决方法:将其定义成一个静态内部类(此时不会持有外部类对象的引用),在构造方法中传入Activity并对Activity对象增加一个弱引用,这样Activity被用户关闭之后,即便异步消息还未处理完毕,Activity也能够被GC回收,从而避免了内存泄露。

	val handler = MyHandler(this)

    class MyHandler(activity: Activity) : Handler() {
        private var reference: WeakReference<Activity>? = null
        init {
            reference = WeakReference<Activity>(activity)
        }
        override fun handleMessage(msg: Message) {
            if (reference?.get() == null) {
                return
            } else {
                when (msg.what) {
                    0 -> {
                        TODO()
                    }
                }
            }
        }
    }
  1. ‘constructor Handler()’ is deprecated

'constructor Handler()' is deprecated. Deprecated in Java

我们进入到Handler.java文件中,会发现无参构造函数已经被deprecated了

    @Deprecated
    public Handler() {
        this(null, false);
    }

官方给出了存在的隐患

     * If this thread does not have a looper, this handler won't be able to receive messages
     * so an exception is thrown.

被弃用的理由

     * @deprecated Implicitly choosing a Looper during Handler construction can lead to bugs
     *   where operations are silently lost (if the Handler is not expecting new tasks and quits),
     *   crashes (if a handler is sometimes created on a thread without a Looper active), or race
     *   conditions, where the thread a handler is associated with is not what the author
     *   anticipated. Instead, use an {@link java.util.concurrent.Executor} or specify the Looper
     *   explicitly, using {@link Looper#getMainLooper}, {link android.view.View#getHandler}, or
     *   similar. If the implicit thread local behavior is required for compatibility, use
     *   {@code new Handler(Looper.myLooper())} to make it clear to readers.

解决方法

  • 使用Handler(@NonNull Looper looper)
  • 使用Handler(@NonNull Looper looper, @Nullable Callback callback)
	val handler = Handler(Looper.getMainLooper())

    val handler = Handler(Looper.getMainLooper(), object : Handler.Callback {
        override fun handleMessage(msg: Message): Boolean {
            TODO("Not yet implemented")
        }
    })

	// lambda
	val handler = Handler(Looper.getMainLooper()
    ) { TODO("Not yet implemented") }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Hovf-1120

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

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

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

打赏作者

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

抵扣说明:

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

余额充值