将 LiveData 与数据绑定一起使用
Posted
技术标签:
【中文标题】将 LiveData 与数据绑定一起使用【英文标题】:Using LiveData with Data Binding 【发布时间】:2018-05-23 10:59:44 【问题描述】:随着 android 架构组件的稳定,我开始将所有基本的ViewModel
s 更新为ViewModel
的新实现。据我了解,建议使用LiveData
来保存Model
类,因为它可以更好地处理生命周期。
我喜欢使用Data Binding
,因为它使 Java/Kotlin 端的代码更清晰,并且不需要“观察”值更改来更新 UI。然而,使用Data Binding
的布局仅在Model
(或ViewModel)扩展BaseObservable
和LiveData
不扩展时才观察数据变化。我了解LiveData
的主要目标之一是观察并以编程方式更新 UI,但对于简单的更新,Data Binding
非常有用。
这个问题已经被报告了(GitHub 和Stack Overflow),最初说 1.0 版会有这个问题,现在说这个功能正在开发中。
为了同时使用LiveData
和Data 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
所以基本上我的ObservableMutableLiveData
是ObservableField
的副本,使用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<String>"/>
</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&lt;String&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<String>"/>
</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 接收到空列表