将 LiveData 与数据绑定一起使用

Posted

技术标签:

【中文标题】将 LiveData 与数据绑定一起使用【英文标题】:Using LiveData with Data Binding 【发布时间】:2018-05-23 10:59:44 【问题描述】:

随着 android 架构组件的稳定,我开始将所有基本的ViewModels 更新为ViewModel 的新实现。据我了解,建议使用LiveData 来保存Model 类,因为它可以更好地处理生命周期。

我喜欢使用Data Binding,因为它使 Java/Kotlin 端的代码更清晰,并且不需要“观察”值更改来更新 UI。然而,使用Data Binding 的布局仅在Model(或ViewModel)扩展BaseObservableLiveData 不扩展时才观察数据变化。我了解LiveData 的主要目标之一是观察并以编程方式更新 UI,但对于简单的更新,Data Binding 非常有用。

这个问题已经被报告了(GitHub 和Stack Overflow),最初说 1.0 版会有这个问题,现在说这个功能正在开发中。

为了同时使用LiveDataData Binding,我创建了一个扩展BaseObservable 的类的非常简单的实现:

import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.databinding.BaseObservable

class ObservableMutableLiveData<T>() : BaseObservable() 

    private var data: MutableLiveData<T> = MutableLiveData()

    constructor(data: T) : this() 
        this.data.value = data
    

    public fun set(value: T) 
        if (value != data.value) 
            data.value = value
            notifyChange()
        
    

    public fun get(): T? 
        return data.value
    

    public fun getObservable(): LiveData<T> 
        return data
    

所以基本上我的ObservableMutableLiveDataObservableField 的副本,使用LiveData 来存储模型,并且通过此实现,每次模型更新后布局都会更新。

问题是:

这是LiveData 的错误实现吗?这个包装器是否“破坏”了LiveData 的功能,例如生命周期感知? 据我了解,LiveData 是新的ObservableField。这是正确的吗?

【问题讨论】:

对实时数据使用数据绑定的正确方法现在在数据绑定的文档中:Use LiveData to notify the UI about data changes。 【参考方案1】:

对于那些遇到这个问题并像我一样寻找示例的人,这里有一个:

在布局.xml 中放入LiveData 元素及其类型:

<layout>
    <data>
        <variable
            name="myString"
            type="android.arch.lifecycle.MutableLiveData&lt;String&gt;"/>
    </data>

    ...

    <TextView
        android:layout_
        android:layout_
        android:text='@myString'
        ...
     />

    ...

</layout>

在您的代码集中,它的价值和生命周期所有者:

MutableLiveData<String> myString = new MutableLiveData<>();

...

binding.setLifecycleOwner(this);
binding.setMyString(myString);

就是这样:)

请注意,LiveData 元素的默认值为 null,因此请分配初始值以确保您立即获得所需的效果,或使用 this 强制可空性。

编辑: 如果您使用androidx,请使用androidx.lifecycle.MutableLiveData&amp;lt;String&amp;gt; 作为类型。

【讨论】:

【参考方案2】:

Android Studio 3.1(目前在 Canary 6 中)将解决这个问题,因为LiveData 可以用作observable field

数据绑定更新:

您现在可以将 LiveData 对象用作数据绑定表达式中的可观察字段。 ViewDataBinding 类现在包含一个新的 setLifecycle 方法,您需要使用它来观察 LiveData 对象。

来源:Android Studio 3.1 Canary 6 is now available

【讨论】:

你能举个例子吗? @kyurkchyan 添加此binding.setLifecycleOwner(this); developer.android.com/topic/libraries/data-binding/…【参考方案3】:

对于 androidx 将是:

androidx.lifecycle.MutableLiveData

<layout>
    <data>
        <variable
            name="myString"
            type="androidx.lifecycle.MutableLiveData&lt;String&gt;"/>
    </data>

    ...

    <TextView
        android:layout_
        android:layout_
        android:text='@myString'
        ...
     />

    ...

</layout>

对于 Kotlin:

  val myStr = MutableLiveData<String>()

...

 binding.apply 
            setLifecycleOwner(this)
            this.myString = myStr
        

祝你好运! :)

【讨论】:

【参考方案4】:

接受的答案没有举例。所以这是我测试过的一个,它可以工作。

在布局中:

<layout>
    <data>
        <variable
            name="viewmodel"
            type="com.abc.xyz.viewmodels.MyViewModel"/>
    </data>

    ...

    <TextView
        android:layout_
        android:layout_
        android:text='@viewmodel.myString'
        ...
     />

    ...

</layout>

在片段中:

override fun onCreateView(inflater: LayoutInflater, 
         container: ViewGroup?, savedInstanceState: Bundle?): View? 
        val binding: FragmentAlbumBinding = DataBindingUtil.inflate(
            inflater, R.layout.fragment_album, container, false)
        binding.apply 
            fragment = this
            viewModel = albumViewModel
            lifecycleOwner = this
    

【讨论】:

以上是关于将 LiveData 与数据绑定一起使用的主要内容,如果未能解决你的问题,请参考以下文章

数据绑定 recyclerview 适配器从 livedata 接收到空列表

将 compose 数据绑定与另一个数据绑定一起使用

将 MVVM 架构中的 Tab 布局与数据绑定库一起使用

如何将数据绑定与 Windows 窗体单选按钮一起使用?

一起Talk Android吧(第三百八十七回:LiveData)

一起Talk Android吧(第三百八十七回:LiveData)