【问题标题】:Android Fragment ViewModel databinding not updating UI even though lifecycleOwner is set即使设置了生命周期所有者,Android Fragment ViewModel 数据绑定也不会更新 UI
【发布时间】:2021-11-27 17:48:01
【问题描述】:

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

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

fragment_checkbox_databinding.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>

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
    }
    ...
}

CheckboxDatabindingFragmentViewModel.kt:

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

    fun startClicked() {
        checkboxEnabled = false
    }
}

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

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

【问题讨论】:

    标签: android kotlin android-fragments android-databinding android-viewmodel


    【解决方案1】:

    问题:

    var checkboxEnabled = true

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

    But, as per documentation:

    设置应该用于观察变化的 LifecycleOwner 此绑定中的 LiveData。如果 LiveData 在绑定之一中 表达式并且没有设置 LifecycleOwner,LiveData 将不会 观察到它的更新不会传播到 UI。

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

    解决办法:

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

    选项 1:使用ObservableBoolean:

    class CheckboxDatabindingFragmentViewModel(application: Application) : AndroidViewModel(application) {
    
        val checkboxEnabled = ObservableBoolean(true)
    
        fun startClicked() {
            checkboxEnabled.set(false)
        }
    }
    

    选项 2:使用 MutableLiveData:

    class CheckboxDatabindingFragmentViewModel(application: Application) : AndroidViewModel(application) {
    
        val checkboxEnabled = MutableLiveData(true)
    
        fun startClicked() {
            checkboxEnabled.value = false
        }
    }
    

    【讨论】:

    • 这是一个清晰而有帮助的答案,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多