0

我在 Android 上开发,我想用下面的代码HandlerThread来启动。countdownTimer

private var bgHandlerThread: HandlerThread? = HandlerThread("MyHandlerThread")

private fun startTimer() {

        bgHandlerThread = HandlerThread("MyHandlerThread")

        bgHandlerThread!!.start()

        val bgHandler = Handler(bgHandlerThread!!.looper)
        bgHandler.post {
            countDownTimer = object : CountDownTimer(COUNT_DOWN_MAX_TIME.toLong(), COUNT_DOWN_INTERVAL.toLong()) {
                override fun onTick(millisUntilFinished: Long) {
                    Log.d(TAG, "time:$millisUntilFinished ")
                }

                override fun onFinish() {
                    Log.d(TAG, "Timer countDown Finish ")

                }
            }.start()
        }
    }

但它显示以下错误

Attempt to read from field 'android.os.MessageQueue android.os.Looper.mQueue' on a null object reference
com.xx.Test.startTimer

所以我想startTimer()onLooperPrepared.

在 Java 中,它类似于以下内容:

@Override
      public void onLooperPrepared() {
}

但是我没有看到kotlin中的方法。onLooperPrepared在 kotlin中使用很热门?

提前致谢。

4

2 回答 2

0

onLooperPrepared()方法是类protected内部的方法HandlerThread.java,没有默认实现。如果要在代码中使用它,则需要在扩展HandlerThread类的类中覆盖它

class YourHandlerThread(val name = "MyHandlerThread") : HandlerThread(name) {
    override fun onLoopPrepared() {...}
    ...
}
于 2019-08-21T15:30:03.183 回答
0

不确定您要实现什么目标,但是如果您想在其他线程上执行某些操作而不阻塞主线程,我强烈建议您开始使用协程,这是在 kotlin 中处理多线程的新推荐方法。

要使用它们,您需要将以下依赖项添加到您的 gradle 文件中:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1'

协程是一大盒不同的巧克力,因此您应该花时间学习这些功能,因为与 java 线程相比,它是一种不同的机制。然而,例如在不同的线程上运行你的计时器很简单:

// it doesn't matter what thread you are currently on
CoroutineScope(Dispatchers.Default).launch {
// the code in brackets runs on a separate thread (read about dispatchers for more information) without blocking the current thread
countDownTimer = object : CountDownTimer(COUNT_DOWN_MAX_TIME.toLong(), COUNT_DOWN_INTERVAL.toLong()) {
                override fun onTick(millisUntilFinished: Long) {
                    Log.d(TAG, "time:$millisUntilFinished ")
                }

                override fun onFinish() {
                    Log.d(TAG, "Timer countDown Finish ")

                }
            }.start()
}

此代码可以正常工作,因为 Log 允许从不同线程发布,但是如果您想更新 UI,这将不起作用,因为 UI 只能从主线程更新。在协程之前,这是一件令人头疼的事情,因为您必须创建一个处理程序并始终发送/接收具有有限能力的消息来取消当前正在运行的任务。使用协程,这很简单:

withContext(Dispatchers.Main) {
// do your ui updates here
}

这个片段可以在你的协程内部使用来切换上下文,你不需要任何东西,一旦你将上下文切换到主线程,你就可以做所有的 UI 更新。

于 2019-08-21T15:31:38.827 回答