Search code examples
androidkotlintimerandroid-jetpack-composekotlin-coroutines

Timer implementation in Android on Kotlin: Should one use coroutine with delay or CountDownTimer


As per the commentary of this answer, using CountDownTimer

val timer=object:CountDownTimer(Long.MAX_VALUE,10){
            override fun onTick(p0: Long) {
                _mutableLiveData.postValue(newValue)
            }
            override fun onFinish() {
                TODO("Not yet implemented")
            }
        }.also { it.start() }

from inside a ViewModel or otherwise would cause memory leaks. On the other hand implementing a timer using viewModelScope.launch

viewModelScope.launch {
            while (true){
                _mutableLiveData.postValue(newValue)
                delay(10)
            }
}

from inside the same ViewModel wastes resources as a thread should exit after performing its task instead of going to sleep.

Which way should I use?

Is there some other idiomatic way that I am missing out?

The context of my question is this: in a ViewModel, my timer implementation (currently using delay) periodically changes the state of a private MutableLiveData that is being observedAsState in a @Composable


Solution

  • A CountDownTimer only leaks memory if you don't clean it up when its associated objects are passing out of scope. So in a ViewModel, you should store a reference to it in a property and call cancel() on it in onCleared(). In an Activity, you'd cancel it in onDestroy(). And so on.

    The viewModelScope is set up to automatically cancel any coroutines it's running when the ViewModel is destroyed, so you don't have to worry about leaks.

    Likewise, lifecycleScope in an Activity or Fragment do the same, and viewLifecycle.lifecycleScope does it for the View life of a Fragment.

    Calling sleep in a thread prevents that thread from doing any work, so it's hogging a core of the processor. And it must never be done on the Main thread because that would lock the UI.

    In a coroutine, delay does not lock up any threads or coroutines, so the same concerns do not apply.