值更新时未调用Android BindingAdapter

一个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,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不遵守视图模型?或者,为什么绑定适配器不触发更新?

感谢您的帮助。

bugandang 回答:值更新时未调用Android BindingAdapter

答案很可能是您没有为片段绑定对象设置lifecycleOwner。 有关更多信息,请参见https://stackoverflow.com/a/56011798/1894338

,

看看我的回答https://stackoverflow.com/a/66488334/9747826

setLifeCyclerOwner 和设置 viewModel 是关键。

,

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()

本文链接:https://www.f2er.com/3169546.html

大家都在问