Launch a coroutine and a regular function from a button

Hello everyone,
I am completly new to koltin, and with coding for android application.

I am trying to understand coroutine scope etc… but it is a bit confusing to me.
I probably don’t have the right mindset with coroutine, but i am gonna attempt to explain what i im trying to do.

The goal of this code is to create a coroutine that update a TextView from a coroutine.
The text has to be 3,2,1, SPIN IT, with delay between.
My idea was to create a coroutine that print the text on the textview when i call the function ttoGO().

Then, I wanted to wait for that coroutine to finish to continue and print someting else.
I want to keep in mind that I can probably use ttoGO() without wainting for it, later.

Thank you for your time.

package com.example.spinos

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.WindowManager
import android.widget.TextView
import kotlinx.coroutines.*

class Score : AppCompatActivity() {

    var resume = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_score)
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)


    }

    fun startscore(view: View?) {

        runBlocking {
            var value = async { ttoGO() }
            println(value.await())
        }
            val textView = findViewById<TextView>(R.id.TextViewScore)
            textView.text = "OKK"
            resume = true

    }

    suspend fun ttoGO(): Int {
        withContext(Dispatchers.Main) {

        val textView = findViewById<TextView>(R.id.TextViewScore)

            textView.text = "3"
            delay(1000)
            textView.text = "2"
            delay(1000)
            textView.text = "1"
            delay(1000)
            textView.text = "SPIN IT !"
            delay(1000)
        }
        return 1
    }

}

I also added this to the xml file :

android:onClick="startscore"

As you can see I am trying to use async and await function. I am not sure this is the good approach.
I want to wait for the button to execute all the rest of my code.

I will take all information that can help me to solve my misunderstanding of coroutine, scope and more…

Thank you for your time.

You didn’t explain if this code works or what is the problem with it. But I guess it freezes the UI.

The problem is that you used runBlocking() inside the main thread which… well, blocks the main thread :wink: Instead, you need to launch a coroutine in the background:

fun startscore(view: View?) {
    lifecycleScope.launch {
        println(ttoGO())
        val textView = findViewById<TextView>(R.id.TextViewScore)
        textView.text = "OKK"
        resume = true
    }
}

BTW, no, using async() and then immediately await() isn’t a good approach. You start a task in the background only to wait for it in the foreground. You can as well invoke ttoGO() directly - it does almost the same thing.

Thank you broot for your answer !
Yes exaclty the UI freezes.

I tried your code, and … It doesn’t update the UI :sweat_smile:
Is it possible i didnt mention something ?

There is my new version

class Score : AppCompatActivity() {

    var resume = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_score)
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)


    }

    fun startscore(view: View?) {


        lifecycleScope.launch {
            ttoGO()
            val textView = findViewById<TextView>(R.id.TextViewScore)
            textView.text = "OKK"
            resume = true
         }
        while (!resume)
            println("false")

            println("true")
    }

    suspend fun ttoGO() {
        withContext(Dispatchers.Main) {

        val textView = findViewById<TextView>(R.id.TextViewScore)

            textView.text = "3"
            delay(1000)
            textView.text = "2"
            delay(1000)
            textView.text = "1"
            delay(1000)
            textView.text = "SPIN IT !"
            delay(1000)
        }
    }

}

The goal is for the main thread to wait for the coroutine to finish.

Thank you in advance.

You can’t wait the main thread to finish the coroutine, because that basically means you block the main thread. You have to let the main thread go and do whatever it needs to do. Then, at the and of launch() (but still inside it) you can perform some additional tasks that you planned to do when the coroutine finishes.