[英]Using LiveData with Data Binding
隨着 Android 架構組件的穩定,我開始將所有基本的ViewModel
更新為ViewModel
的新實現。 在我的理解中,推薦使用LiveData
來保存Model
類,因為它可以更好地處理生命周期。
我喜歡使用Data Binding
因為它使 Java/Kotlin 端的代碼更清晰,並且不需要“觀察”值更改來更新 UI。 然而,如果Model
(或視圖模型)擴展BaseObservable
而LiveData
沒有,則使用Data Binding
的布局僅觀察數據更改。 我知道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
。 這樣對嗎?對於那些遇到這個問題並像我一樣尋找例子的人,這里有一個:
在布局.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
因此分配初始值以確保您立即獲得所需的效果或使用它來強制為可空性。
編輯:使用androidx.lifecycle.MutableLiveData<String>
如果您使用androidx
類型。
Android Studio 3.1(目前在 Canary 6 中)將解決這個問題,因為LiveData
可以用作observable field
:
數據綁定更新:
您現在可以將 LiveData 對象用作數據綁定表達式中的可觀察字段。 ViewDataBinding 類現在包含一個新的 setLifecycle 方法,您需要使用該方法來觀察 LiveData 對象。
對於 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
}
祝你好運! :)
接受的答案沒有舉例。 所以這是我測試過的一個,它有效。
在布局中:
<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
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.