Reputation: 1074
I want to bind a button click to a suspended function inside viewmodel.
this is my code:
RegistrationActivityViewModel.kt
suspend fun register() {
if (validateFields()) {
val result = SourceplusplusApiService.invoke().registerUser(username.value!!, email.value!!, password.value!!).await()
isRegistrationCompleted.value = getResultValue(result)
}
}
activity_registration.xml
<Button
android:text="Register"
android:onClick="@{()->viewmodel.register()}"
android:textSize="16sp" />
i get a databinding error that says ActivityRegistrationBindingImpl
not generated. after searching a lot i realized that when i remove the suspend
keyword and comment the code inside, it works fine but it has to be a suspended function.
Does anyone know how to fix it?
Upvotes: 3
Views: 5537
Reputation: 1007276
You cannot data bind to a suspend
function, and IMHO a viewmodel should not be exposing a suspend
function in the first place. I recommend:
Step #1: Remove the suspend
keyword from register()
Step #2: Rewrite register()
to run your code in a suitable coroutine scope, so any suspend
functions that it calls are handled properly:
fun register() {
viewModelScope.launch(Dispatchers.Main) {
if (validateFields()) {
val result = SourceplusplusApiService.invoke().registerUser(username.value!!, email.value!!, password.value!!).await()
isRegistrationCompleted.value = getResultValue(result)
}
}
}
Here, I am using the viewModelScope
option provided by androidx.lifecycle:lifecycle-viewmodel-ktx
version 2.1.0-alpha01
and newer. Alternatively, manage your own coroutine scope. Dispatchers.Main
will ensure that any results of that work is available to you on the Android main application thread.
Now, your data binding expression can refer to register()
, while you still have a coroutine scope for calling downstream suspend
functions.
Upvotes: 7