首页 > 解决方案 > 为什么我在主线程中发布了一个 Runnable,但 Runnable 是在 HandlerThread 中执行的?

问题描述

这是有问题的代码:

object MainThreadPoster : Handler(Looper.getMainLooper()) {

    fun postRunnableAtFixRate(runnable: Runnable, token: Any, delay: Long, period: Long) {
        postAtTime(object : Runnable {
            override fun run() {
                runnable.run()
            }
        }, token, SystemClock.uptimeMillis() + delay)
    }

}

MainThreadPoster 是用 mainLooper 初始化的,所以 runnable 函数(在 postRunnableAtFixRate 方法中)预计会在主线程中执行,但问题是 runnable 函数有时可能会在 HandlerThread 中执行。

这是预期的堆栈跟踪 这是预期的堆栈跟踪

这是有问题的堆栈跟踪 这是有问题的堆栈跟踪

标签: androidhandler

解决方案


不要在代码中调用 Message.recycle()。在Android 4.4中,如果多次调用Message.recycle(),消息会多次出现在消息池中,消息可能同时存在于多个消息队列中。</p>

这是 poc:

class MainActivity : AppCompatActivity() {
    private val mMainHandler = Handler(Looper.getMainLooper())
    private lateinit var mSubHandler: Handler

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        btn_test.setOnClickListener {
            start()
        }

        val handlerThread = HandlerThread("sub thread")
        handlerThread.start()
        mSubHandler = Handler(handlerThread.looper)
    }

    private fun start(){
        val message = Message()
        message.recycle()
        message.recycle()

        mMainHandler.postDelayed({
            if(Looper.myLooper() != Looper.getMainLooper()){
                throw Exception("should run in main thread")
            }

            start()
        }, 100)

        mSubHandler.sendEmptyMessage(1)
    }
}

推荐阅读