chrisChris
chrisChris

Reputation: 99

How to await for value using Coroutines with viewModelScope

How to await for value using Coroutine suspend method in viewModel in most efficient way.

My solution for now:

   viewModelScope.launch {
                val item = async { itemRepository.getItem(id) }.await()
print("log me after not null $item)
}

Kotlin converts it to and the question is also why? :)

   viewModelScope.launch {
                    withContext(Dispatchers.Default) {
                        itemRepository.getItem(id)
                    }
print("log me after not null $item)
}

my suspend funct

    suspend fun geItem(itemId: Int): ItemRoom? = getItemByIdUseCase.build(itemId)

++ method from here \/

class GetItemByIdUseCase(private val itemDao: ItemDao) :
    BaseUseCase<Int, ItemRoom>() {
    override suspend fun create(id: Int): ItemRoom {
        return itemDao.getItemById(id)
    }

}

++ method from here \/

    @Query("SELECT * FROM item WHERE id=:id")
    abstract suspend fun getItemById(id: Int): ItemRoom

Upvotes: 1

Views: 2777

Answers (1)

Tenfour04
Tenfour04

Reputation: 93521

async { /* ... */ }.await() is a more convoluted version of withContext { }. There's no reason to use async if you are going to immediately await its result, because you are ultimately using it to synchronously get a result (synchronous, but suspending). The compiler probably warns you because if you do something that doesn't really make sense or is needlessly convoluted, it's likely you're doing something wrong or don't understand what you're doing.

In this case, you don't even need withContext(), because the only thing in your lambda is a suspend function call. You can freely call suspend functions synchronously inside coroutines and other suspend functions without worrying about coroutine context (as long as these functions are non-blocking, as any suspend function generated by Room would be).

viewModelScope.launch {
    val item = itemRepository.getItem(id)
    print("log me after not null $item")
}

This is the core concept of a suspend function. You can call it synchronously without it blocking the current thread.

I'm guessing the compiler warning just isn't sophisticated enough to tell that you don't need withContext, since it can't 100% guarantee you aren't calling a blocking function. Maybe it just assumes you were calling something blocking if you were trying to use async.

Upvotes: 2

Related Questions