Kotlin中使用Handler(无内存泄露)

Java中使用Handler相信大家都知道,所以这篇文章就告诉大家在Kotlin中怎么使用Handler
对kotlin函数不太了解的同学可以看看这篇文章
kotlin基本函数的使用 - (jianshu.com)

一. 最简写法

class MainActivity : AppCompatActivity() {
    private val WHAT = 100

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Thread {
            mHandler.sendMessage(Message.obtain().apply {
                what = WHAT
                obj = "你好"
            })
        }.start()
    }

    private val mHandler = Handler(mainLooper) {
        when (it.what) {
            WHAT -> Log.d("mHandler:", "${it.obj}")
        }
        false
    }
}

以上写法是经过高阶函数和lambda表达式简化的,实际调用的是两个参数的构造方法,闭包是Callback.handleMessage,所以需要有一个返回值。

    public Handler(@NonNull Looper looper, @Nullable Callback callback) {
        this(looper, callback, false);
    }

匿名内部类会持有外部类的引用,所以mHandler会持有MainActivity的引用,Message又会持有mHandler的引用,等于Message间接持有了MainActivity的引用。如果通过mHandler发送的是延迟消息,那么在Message进入消息队列等待的过程中会一直持有MainActivity的引用,即使MainActivity在等待消息送达的过程中finish掉了也不会被系统回收,这样就造成了Handler引起的内存泄漏问题。

二. 无内存泄漏写法

class MainActivity : AppCompatActivity() {
    private lateinit var tvName: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tvName = findViewById(R.id.tv_name)
        Thread {
            mHandler.sendMessageDelayed(Message.obtain().apply {
                what = WHAT
                obj = "你好"
            }, 5000)
        }.start()
    }

    private val mHandler = MyHandler(WeakReference(this))

    private class MyHandler(val wrActivity: WeakReference) : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            wrActivity.get()?.run {
                when (msg.what) {
                    WHAT -> tvName.text = msg.obj as String
                }
            }
        }
    }

    companion object {
        const val WHAT = 100
    }
}

实现原理与Java版一样,也是通过WeakReference弱引用方式解决。这里是重写的父类Handler的handleMessage,所以不需要返回值。

你可能感兴趣的:(Kotlin中使用Handler(无内存泄露))