0

I am developing in Android, I want to use HandlerThread to start a countdownTimer like the following code.

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()
        }
    }

But it show the following error

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

So I want to move the startTimer() to the onLooperPrepared.

In Java, it is like the following:

@Override
      public void onLooperPrepared() {
}

But I did not see the method in kotlin. Hot to use the onLooperPrepared in kotlin ?

Thanks in advance.

Wun
  • 6,211
  • 11
  • 56
  • 101

2 Answers2

0

The onLooperPrepared() method is a protected method inside of the HandlerThread.java class, with no default implementation. If you want to use it in your code, you'd need to override it in a class that extends the HandlerThread class

class YourHandlerThread(val name = "MyHandlerThread") : HandlerThread(name) {
    override fun onLoopPrepared() {...}
    ...
}
Rafa
  • 3,219
  • 4
  • 38
  • 70
0

Not sure what are you trying to achieve, however if you want to execute something on other thread without blocking the main thread I HIGHLY recommend to start using coroutines, this is the new and recommended way to handle multi threading in kotlin.

To use them you will need to add the following dependencies to your gradle file:

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

Coroutines are a big box of different chocolates so you should take your time to learn the capabilities, since it is a different mechanism compared to java threads. However for example to run your timer on a different thread is as easy as:

// 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()
}

This code will work without any problems since Log allows posting from different threads, however this will not work in case when you want to update UI, since UI can be updated only from the main thread. Before coroutines this was a pain in the ass since you had to make a handler and always send/receive messages with limited capability on cancelling the currently running task. With coroutines this is as easy as:

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

This snippet can be used inside of your coroutine to switch the context, you don't need anything more, once you switch the context to main thread you can do all the UI updates.

Daniel
  • 2,320
  • 1
  • 14
  • 27