Search code examples
androidkotlinkotlin-coroutines

Coroutines delay not freeze, but while freeze


I am trying to understand how coroutines work

with bellow code, the UI is not freezing

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    val scope = CoroutineScope(Dispatchers.Main)
    binding.root.setOnClickListener {
        scope.launch {
            delay(1000)
        }
    }
}

But with bellow code, the UI is freezing

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    val scope = CoroutineScope(Dispatchers.Main)
    binding.root.setOnClickListener {
        scope.launch {
            myOwnDelayCode()
        }
    }
}

suspend fun myOwnDelayCode() {
    val date = System.currentTimeMillis()
    while(System.currentTimeMillis() - date < 1000) {}
}

Why does it happen eventhough i put "suspend" to my function?


Solution

  • Because delay doesn't busy loop, it suspends.

    Your while loop is going to constantly call currentTimeMillis, subtract the times, and check if the loop is done. It will infinitely loop until then. This is called a busy loop, the processor is constantly working. This results in a freeze.

    Calling delay does NOT infinitely do work. It marks the coroutine as waiting until a certain time (1000ms from now) to continue. It will then yield this thread to any other coroutines that are ready to run now, and they will get a chance to run. Then when the time is passed and nothing else is running, it will pick up this coroutine where it left off and continue. The code it generates to do this is complicated, but you can basically imagine there being a list of functions that are ready to run, and those that are waiting. Delay() puts this coroutine in a list of things waiting forlater, and then calls the first coroutine that's ready to run. And then every time something it runs finishes, it will check if anything in the waiting state is ready and move it to the other queue if needed.