CallMePedro
CallMePedro

Reputation: 91

Android multithreading - coroutine and UI thread

I am new to multithreading and looking for solution for this problem. I am launching a method in coroutine which updates data in my database and if it is updated I would like to update the UI for users. How to this? I cannot put runOnUiThread inside a coroutine. Is there some type of magic like -> when coroutine finished -> then -> runOnUi?

Greetings

Upvotes: 3

Views: 2481

Answers (3)

Tushar Saha
Tushar Saha

Reputation: 2106

So the basic problem is to jumping back to main thread after co-routine finishes

this can be done multiple ways

using launch(Dispatcher.Main)

from main thread init co-routine something like this

//launches coroutine running on main thread
GlobalScope.launch(Dispatchers.Main) {
    updateDb()
}

suspend fun updateDb(){
    //runs on worker thread and returns data
    val value = withContext(Dispatchers.IO){
       saveDataInDb();
    }
    //runs back on main thread
    updateUI(value);
}

However global scope should not be used You can read about that here https://medium.com/@elizarov/the-reason-to-avoid-globalscope-835337445abc

using async await

suspend fun saveInDb() {
    val value = GlobalScope.async {
        delay(1000)
        println("thread running on [${Thread.currentThread().name}]")
        10
    }
    println("value =  ${value.await()} thread running on [${Thread.currentThread().name}]")
}

output:

 thread running on [DefaultDispatcher-worker-1]
 value =  10 thread running on [main]
 thread running on [main]

Upvotes: 1

Froyo
Froyo

Reputation: 18477

You don't need to call runOnUiThread as the coroutine will have the main dispatcher as the context.

Let's say you have this helper function to offload work to the I/O thread.

suspend fun <T> withIO(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block)

If you are using a ViewModel, then you can call it like this

viewModelScope.launch {
    val result = withIO { 
        // You are on IO thread here.
        update your database
    }
    // The block will be suspended until the above task is done.
    // You are on UI thread now.
    // Update your UI.
}

If you are not using a ViewModel, you can also use

withContext(Disptachers.Main) {
   val result = withIO {
       // You are on IO thread
   }
   // You are back on the main thread with the result from the task
}

Upvotes: 4

Dak28
Dak28

Reputation: 259

Coroutine are task that work on different thread. What you really want is wating for changes in database. Coroutine in this idea could work for insert data in db, but listening part is role of ViewModel pattern.

I recently answer similar question to yours:

AutocompleteTextView with room

More specific could be this answer from another user:

Wait until Kotlin coroutine finishes in onCreateView()

Upvotes: 1

Related Questions