为什么我将Runnable发布到主线程中,但是Runnable是在HandlerThread中执行的?

时间:2019-05-10 06:03:58

标签: android handler

这是有问题的代码:

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初始化,因此可运行函数(在postRunnableAtFixRate方法中)有望在主线程中执行,但是问题是可运行函数有时可能在HandlerThread中执行。

这是预期的堆栈跟踪 This is the expected stack trace

这是有问题的堆栈跟踪 This is the stack trace with problem

1 个答案:

答案 0 :(得分:0)

请勿在您的代码中调用Message.recycle()。在Android 4.4中,如果多次调用Message.recycle(),则该消息将在消息池中多次出现,并且该消息可能同时存在于多消息队列中。

这是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)
    }
}