随着Android体系结构组件的稳定,我开始将所有基本ViewModel
更新为ViewModel
的新实现。根据我的理解,建议使用LiveData
来保存Model
类,因为它可以更好地处理生命周期。
我喜欢使用Data Binding
,因为它使代码在Java / Kotlin方面更加清晰,并且不需要"观看"值更改以更新UI。但是,如果Data Binding
(或ViewModel)扩展BaseObservable
而Model
不扩展,则使用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
的错误实现吗?这个包装器是否会破坏&#34; LiveData
的功能,例如生命周期感知?LiveData
是新ObservableField
。这是对的吗?答案 0 :(得分:14)
对于那些遇到这个问题寻找像我一样的例子的人来说,这里有一个:
在布局.xml
中,将LiveData
元素添加到其中:
<layout>
<data>
<variable
name="myString"
type="android.arch.lifecycle.MutableLiveData<String>"/>
</data>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{myString}'
...
/>
...
</layout>
在您的代码中设置它的值和生命周期所有者:
MutableLiveData<String> myString = new MutableLiveData<>();
...
binding.setLifecycleOwner(this);
binding.setMyString(myString);
那就是:)
请注意,LiveData
元素的默认值为null
,因此请指定初始值,以确保立即获得所需效果,或使用this强制执行可为空性。
答案 1 :(得分:13)
Android Studio 3.1(目前位于Canary 6中)将解决此问题,因为LiveData
可用作observable field
:
数据绑定的更新:
现在,您可以将LiveData对象用作数据绑定表达式中的可观察字段。 ViewDataBinding类现在包含一个新的setLifecycle方法,您需要将其用于观察LiveData对象。
答案 2 :(得分:1)
接受的答案没有给出示例。所以这是我测试过的,可以正常工作。
在布局中:
<layout>
<data>
<variable
name="viewmodel"
type="com.abc.xyz.viewmodels.MyViewModel"/>
</data>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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
}
}
答案 3 :(得分:0)
对于androidx,将是:
androidx.lifecycle.MutableLiveData
<layout>
<data>
<variable
name="myString"
type="androidx.lifecycle.MutableLiveData;String>"/>
</data>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{myString}'
...
/>
...
</layout>
对于Kotlin:
val myStr = MutableLiveData<String>()
...
binding.apply {
setLifecycleOwner(this)
this.myString = myStr
}
祝你好运! :)