Ofir Bar
02/19/2020, 4:28 PMreturnedExpertiseFields
inside a ViewModel.
I want to initialize this list using a query to Room.
returnedExpertiseFields
gets returned before it is initialized with values from Room, as in the code below:
fun getExpertiseFieldsById(expertiseFieldsIds: IntArray) : List<ExpertiseField>{
var returnedExpertiseFields = listOf<ExpertiseField>()
viewModelScope.launch {
returnedExpertiseFields = mExpertiseFieldFieldsRepository.getExpertiseFieldsFromDatabaseById(expertiseFieldsIds)
}
return returnedExpertiseFields
}
returnedExpertiseFields
will return an empty list of ExpertiseField
.
What can I do to make sure I always wait to Room query to be returned? I thought calling launch is synchronous?
(If you need my repository code I will post it, I just thought it might not be necessary)
Also, If any of you have any tips for debugging when using coroutines I will be glad to hear. I initially tought my Room query is broken. After long debugging I realized I am jumping between breakpoints rather them skipping them.Oleg Siboglov
02/19/2020, 4:43 PMfun getExpertiseFieldsById(expertiseFieldsIds: IntArray) : List<ExpertiseField> = withContext(<http://Dispatches.IO|Dispatches.IO>) {
mExpertiseFieldFieldsRepository.getExpertiseFieldsFromDatabaseById(expertiseFieldsIds)
}
Then you would call this method like so.
fun someMethod() {
viewModelScope.lauch {
val returnedExpertiseFields = getExpertiseFieldsById(ids)
// do something with the fields
}
}
Brian
02/19/2020, 4:44 PMLiveData
in the view model and observing that? something like:
val expertiseFields = MutableLiveData<List<ExpertiseField>>()
fun getExpertiseFieldsById(expertiseFieldsIds: IntArray) {
viewModelScope.launch {
expertiseFields.postValue(mExpertiseFieldFieldsRepository.getExpertiseFieldsFromDatabaseById(expertiseFieldsIds))
}
}
and then, from your activity or fragment:
// ... inside on onCreate or onViewCreated, for example
yourViewModel.expertiseFields.observe(this, { expertiseFields ->
// expertiseFields is your list
})
Ofir Bar
02/19/2020, 4:51 PMOfir Bar
02/19/2020, 4:52 PMBrian
02/19/2020, 4:54 PMviewModelScope
Oleg Siboglov
02/19/2020, 4:55 PM<http://Dispatchers.IO|Dispatchers.IO>
?Oleg Siboglov
02/19/2020, 4:56 PMOfir Bar
02/19/2020, 4:57 PMOfir Bar
02/19/2020, 5:00 PMprivate fun someMethod(expertiseFieldsIds: IntArray) : List<ExpertiseField>{
viewModelScope.launch {
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
mExpertiseFieldFieldsRepository.getExpertiseFieldsFromDatabaseById(expertiseFieldsIds)
}
}
}
How can I return value from an IO context?Oleg Siboglov
02/19/2020, 5:02 PMviewModelScope.launch {
returnedExpertiseFields = mExpertiseFieldFieldsRepository.getExpertiseFieldsFromDatabaseById(expertiseFieldsIds)
}
launch
here is consuming an exception that Room
would throw warning you about running a query on the main thread.Oleg Siboglov
02/19/2020, 5:07 PMfun someMethod() {
viewModelScope.launch {
val ids = getIds()
val fields = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
mExpertiseFieldFieldsRepository.getExpertiseFieldsFromDatabaseById(ids)
}
//do something with fields
}
}
Ofir Bar
02/19/2020, 5:15 PMOleg Siboglov
02/19/2020, 5:24 PMViewModel
and instead use MVP, so I don’t know all the capabilities of ViewModel
. However heres an example where view
is a reference to your UI.
fun loadFields() {
CoroutineScope(Dispatchers.Main).launch {
val ids = getIds()
val fields = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
mExpertiseFieldFieldsRepository.getExpertiseFieldsFromDatabaseById(ids)
}
// This coroutine is suspended until the room query completes. When it does complete, this coroutine is resumed and you can update the UI since you are back to using Dispatchers.Main
view.updateAdapterWithFields(fields)
}
}
Oleg Siboglov
02/19/2020, 5:28 PMRoom
and ViewModel
- https://codelabs.developers.google.com/codelabs/kotlin-coroutines/#2