一个Activity
,两个Fragment
共享一个公用ViewModel
。我已验证视图模型引用在每个片段中都是相同的。
在片段一的布局XML中,有一个TextInputLayout
。片段二使用布尔值更新视图模型。文本输入布局正在观察该值,并且在更改值时应调用BindingAdapter
。
实例化片段且其布局被放大时,绑定适配器将触发,因此我知道该视图正在观察该值。但是,稍后,当片段2更新该值时,片段1中的视图不会触发绑定适配器。
这在片段1的onCreateView()
中:
registrationViewModel = activity?.run {
ViewModelProviders
.of(this, RegistrationViewModelFactory(prefs, dataFetcherService))
.get(RegistrationViewModel::class.java)
} ?: throw Exception("Invalid Activity")
这是观察该视图模型的视图:
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/reg_auth_code_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:errorState="@{registrationViewModel.registrationData.authorizationError}"
bind:errorMessage="@{@string/invalid_auth_code}">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/reg_auth_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{registrationViewModel.registrationData.authCode}"
android:hint="@string/enter_auth_code"
android:maxLines="1"
android:inputType="text"
android:imeOptions="actionDone"
app:autoSizeTextType="uniform"/>
</com.google.android.material.textfield.TextInputLayout>
对于片段2,onCreateView()中的相同代码:
registrationViewModel = activity?.run {
ViewModelProviders
.of(this, RegistrationViewModelFactory(prefs, dataFetcherService))
.get(RegistrationViewModel::class.java)
} ?: throw Exception("Invalid Activity")
单击按钮时,片段二会触发视图模型中的活动:
private fun attemptNavigationToUserData() {
viewModelScope.launch {
isAuthorized = runBlocking { useCase.isAuthorized() }
registrationData.value?.authorizationError = !isAuthorized
}
}
最后,这是BindingAdapter:
@BindingAdapter("errorState", "errorMessage")
fun setErrorState(
textInputLayout: TextInputLayout?,
errorState: Boolean,
errorMessage: String) {
textInputLayout?.let {
it.isErrorEnabled = errorState
if (errorState) it.error = errorMessage
}
}
所有这些似乎都已正确设置,AFAIK。正如我所提到的,绑定适配器会在视图最初被放大时触发,但是再也不会触发。
为什么我的XML不遵守视图模型?或者,为什么绑定适配器不触发更新?
感谢您的帮助。
答案 0 :(得分:0)
答案很可能是您没有为片段绑定对象设置lifecycleOwner。 有关更多信息,请参见https://stackoverflow.com/a/56011798/1894338
答案 1 :(得分:0)
看看我的回答https://stackoverflow.com/a/66488334/9747826
setLifeCyclerOwner 和设置 viewModel 是关键。
答案 2 :(得分:0)
您 authorizationError
应该是 LiveData<>
。这样当 LiveData 的值 (errorState
) 更新时,BindingAdapter 方法将自动调用。
如果您希望 BindingAdapter 方法接收自动更新,则应在 dataBinding 表达式中使用 LiveData。
如:
subTitleText="@{removableItemsViewModel.removableItemsInfo}"
以及 BindingAdapter 方法和 LiveData:
val removableItemsInfo: LiveData<Pair<Int, Long>>
-----------------------------------------------------
@BindingAdapter("subTitleText")
fun setSubTitleText(textView: TextView, pair: Pair<Int, Long>){
}
另外,不要忘记调用 binding.setLifecycleOwner()