即使设置了lifecycleOwner,Android Fragment ViewModel数据绑定也不会更新UI

Dan*_*obs 2 android android-fragments kotlin android-databinding android-viewmodel

ViewModel我想在单击按钮时使用带有数据绑定的复选框来禁用复选框,但除非片段被销毁并重新创建,否则 UI 不会更新。

似乎有很多类似的问题,但最相似的问题似乎都可以通过设置来解决binding.lifecycleOwner,我已经完成了。

片段_复选框_数据绑定.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".CheckboxDatabindingFragment">
    
    <data>
        <variable
            name="viewModel"
            type=".CheckboxDatabindingFragmentViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <CheckBox
            android:id="@+id/my_checkbox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="@{viewModel.checkboxEnabled}" />

        <Button
            android:id="@+id/my_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{() -> viewModel.startClicked()}" />
    
    </LinearLayout>
</layout>
Run Code Online (Sandbox Code Playgroud)

CheckboxDatabindingFragment.kt:

class CheckboxDatabindingFragment() : Fragment() {
    private lateinit var viewModel: CheckboxDatabindingFragmentViewModel

    private var _binding: FragmentCheckboxDatabindingBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        viewModel = ViewModelProvider(this).get(CheckboxDatabindingFragmentViewModel::class.java )
        
        _binding = FragmentCheckboxDatabindingBinding.inflate(inflater, container, false)
        binding.lifecycleOwner = viewLifecycleOwner // androidx.fragment.app.FragmentViewLifecycleOwner
        binding.viewModel = viewModel
        
        return binding.root
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

CheckboxDatabindingFragmentViewModel.kt:

class CheckboxDatabindingFragmentViewModel(application: Application) : AndroidViewModel(application) {
    var checkboxEnabled = true

    fun startClicked() {
        checkboxEnabled = false
    }
}
Run Code Online (Sandbox Code Playgroud)

CheckboxDatabindingFragment.kt我知道我可以通过手动获取复选框视图并设置属性来轻松执行此功能isEnabled,但这违背了数据绑定的目的。

我需要片段而不是活动作为所有者,那么如何更新片段 UI?

Zai*_*ain 5

问题:

var checkboxEnabled = true

top 语句创建一个不可观察的布尔值,因此无法观察到该变量的任何更改,也无法通过生命周期所有者(在您的情况下是片段)将其提交到布局。

但是,根据文档:

设置用于观察此绑定中 LiveData 变化的 LifecycleOwner。如果 LiveData 位于绑定表达式之一中并且未设置 LifecycleOwner,则不会观察到 LiveData,并且对其的更新也不会传播到 UI。

因此,binding.lifecycleOwner = viewLifecycleOwner单独使用不足以通过数据绑定发布对布局的更改,还必须使用可以被 lifeCycleOwner 观察到的可观察对象,并最终通过 DataBinding 将它们的任何更改发布到布局。

解决方案:

要解决这个问题,您需要将 更改checkboxEnabled为可观察的:

选项 1:使用ObservableBoolean

class CheckboxDatabindingFragmentViewModel(application: Application) : AndroidViewModel(application) {

    val checkboxEnabled = ObservableBoolean(true)

    fun startClicked() {
        checkboxEnabled.set(false)
    }
}
Run Code Online (Sandbox Code Playgroud)

选项 2:使用MutableLiveData

class CheckboxDatabindingFragmentViewModel(application: Application) : AndroidViewModel(application) {

    val checkboxEnabled = MutableLiveData(true)

    fun startClicked() {
        checkboxEnabled.value = false
    }
}
Run Code Online (Sandbox Code Playgroud)