Home > Enterprise >  What's the proper way to switch between IO and UI in Kotlin coroutine?
What's the proper way to switch between IO and UI in Kotlin coroutine?

Time:08-17

I'm launching a coroutine in a view model to do some IO operation such as api call and database queries. I know there are few ways it can be done that's why it's confusing to me which is the right approach.

What's the difference between the two and which is the proper approach?

fun loadProducts() {
    viewModelScope.launch {    
        val productsDeferred = async(Dispatchers.IO) { downloadProducts() }
        this.products = productsDeferred.await()        
    }
}


fun loadProducts2() {
    viewModelScope.launch {    
        this.products = withContext(Dispatchers.IO) { downloadProducts() }
    }
}

In this example I'm using a flow to load products from roomdb. I wanted the changes in db to reflect to the UI that's why I used a flow. Do I need to switch context to Dispatchers.IO when calling loadProductsFromDatabaseAsFlow and then switch to Main in the collect block? Again, what's the proper way to do that?

fun loadProducts3() {
    viewModelScope.launch {
        loadProductsFromDatabaseAsFlow().collect {
            this.products = it
        }
    }
}

CodePudding user response:

What's the difference between the two and which is the proper approach?

async is mainly used for parallel execution of tasks, that return some result. In your case you launch only one task so I would say that withContext(Dispatchers.IO) is preferred here.

Do I need to switch context to Dispatchers.IO when calling loadProductsFromDatabaseAsFlow and then switch to Main in the collect block?

No, you don't need to. You can collect data without switching the context. Flow.collect() method is suspend, one of the main purposes of suspend methods is to be called in the Main context without blocking the Main thread. They just suspend the coroutine, but not the current thread.

  • Related