谷歌推出的LiveData和RxJava類似洽瞬,也是基于觀察者本涕,你可以認(rèn)為LiveData是輕量級的RxJava。起初LiveData并不被看好片任,隨著谷歌的大力推廣偏友,LiveData也慢慢的進(jìn)入了大家的視野蔬胯。一般來說对供,LiveData很少單獨(dú)使用,它更多的和Android
Jetpack的其他組件搭配使用氛濒,比如和ViewModel产场、Room、Paging等舞竿。這篇文章就來介紹LiveData的使用京景。
一、定義
LiveData
是一種可觀察的數(shù)據(jù)存儲器類骗奖。與常規(guī)的可觀察類不同确徙,LiveData 具有生命周期感知能力,意指它遵循其他應(yīng)用組件(如 Activity执桌、Fragment 或 Service)的生命周期鄙皇。這種感知能力可確保 LiveData 僅更新處于活躍生命周期狀態(tài)的應(yīng)用組件觀察者。
二仰挣、優(yōu)勢:
使用 LiveData 具有以下優(yōu)勢:
-
確保界面符合數(shù)據(jù)狀態(tài)
LiveData 遵循觀察者模式伴逸。當(dāng)生命周期狀態(tài)發(fā)生變化時,LiveData 會通知
Observer
對象膘壶。您可以整合代碼以在這些Observer
對象中更新界面错蝴。觀察者可以在每次發(fā)生更改時更新界面洲愤,而不是在每次應(yīng)用數(shù)據(jù)發(fā)生更改時更新界面。 -
不會發(fā)生內(nèi)存泄露
觀察者會綁定到
Lifecycle
對象顷锰,并在其關(guān)聯(lián)的生命周期遭到銷毀后進(jìn)行自我清理柬赐。 -
不會因 Activity 停止而導(dǎo)致崩潰
如果觀察者的生命周期處于非活躍狀態(tài)(如返回棧中的 Activity),則它不會接收任何 LiveData 事件官紫。
-
不再需要手動處理生命周期
界面組件只是觀察相關(guān)數(shù)據(jù)躺率,不會停止或恢復(fù)觀察。LiveData 將自動管理所有這些操作万矾,因為它在觀察時可以感知相關(guān)的生命周期狀態(tài)變化悼吱。
-
數(shù)據(jù)始終保持最新狀態(tài)
如果生命周期變?yōu)榉腔钴S狀態(tài),它會在再次變?yōu)榛钴S狀態(tài)時接收最新的數(shù)據(jù)良狈。例如后添,曾經(jīng)在后臺的 Activity 會在返回前臺后立即接收最新的數(shù)據(jù)。
-
適當(dāng)?shù)呐渲酶?/strong>
如果由于配置更改(如設(shè)備旋轉(zhuǎn))而重新創(chuàng)建了 Activity 或 Fragment薪丁,它會立即接收最新的可用數(shù)據(jù)遇西。
-
共享資源
您可以使用單一實例模式擴(kuò)展
LiveData
對象以封裝系統(tǒng)服務(wù),以便在應(yīng)用中共享它們严嗜。LiveData
對象連接到系統(tǒng)服務(wù)一次粱檀,然后需要相應(yīng)資源的任何觀察者只需觀察LiveData
對象,后文都會提高
三漫玄、使用liveData
LiveData的數(shù)據(jù)源一般是ViewModel茄蚯,也可以是其它可以更新LiveData的組件。當(dāng)數(shù)據(jù)更新后睦优,LiveData 就會通知它的所有觀察者渗常,比如Activiy。
與RxJava的方法不同的是汗盘,LiveData并不是通知所有觀察者皱碘,它只會通知處于Active狀態(tài)的觀察者,如果一個觀察者處于Paused或Destroyed狀態(tài)隐孽,它將不會收到通知癌椿。
這對于Activiy和Service特別有用,因為它們可以安全地觀察LiveData對象而不用擔(dān)心內(nèi)存泄漏的問題菱阵。開發(fā)者也不需要在onPause或onDestroy方法中解除對LiveData的訂閱踢俄。還有一點(diǎn)需要注意的是一旦觀察者重新恢復(fù)Resumed狀態(tài),它將會重新收到LiveData的最新數(shù)據(jù)送粱。
3.1褪贵、 LiveData的基本使用
示例為Button事件點(diǎn)擊,LiveData發(fā)送個數(shù)據(jù),觀察者接收到數(shù)據(jù)更新以后更新UI
class LiveDataActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_live_data)
var liveData: LiveData<String> = MutableLiveData<String>()
btn_ald_post.setOnClickListener {
//發(fā)送數(shù)據(jù)
(liveData as MutableLiveData).postValue("有新消息了")
}
//觀察livedata對象
liveData.observe(this, Observer<String> {
//Updata UI
tv_ald_info.text = it
})
}
}
liveData.observe(this脆丁,Observer<String>)方法有兩個參數(shù)分別是LifecycleOwner
和 Observer
世舰,第一個參數(shù)就是LiveDataActivity本身,因為父類已實現(xiàn)了LifecycleOwner接口,詳情可參考筆者Lifecycle的文章槽卫,第二個參數(shù)則新建了一個Observer
跟压,在onChanged方法中得到回調(diào)。注釋處的postValue方法會在主線程中更新數(shù)據(jù)歼培,這樣就會更改TextView中text屬性的值震蒋。
在大多數(shù)情況下,LiveData的observe方法會放在onCreate方法中躲庄,如果放在onResume方法中查剖,會出現(xiàn)多次調(diào)用的問題。除了MutableLiveData的postValue方法噪窘,還可以使用setValue方法笋庄,它們之前的區(qū)別是,setValue方法必須在主線程使用倔监,如果是在工作線程中更新LiveData直砂,則可以使用postValue方法。
3.2浩习、 更改LiveData中的數(shù)據(jù)
如果我們想要在LiveData對象分發(fā)給觀察者之前對其中存儲的值進(jìn)行更改静暂,可以使用Transformations.map()
和Transformations.switchMap()
,類似于Rxjava中的map()方法
下面通過簡單的例子來講解它們
var liveData: LiveData<String> = MutableLiveData<String>()
btn_ald_post.setOnClickListener {
(liveData as MutableLiveData).postValue("有新消息了")
}
var changLiveData = Transformations.map(liveData) {
it + "changed"
}
changLiveData.observe(this, Observer<String> {
tv_ald_info.text = it
})
運(yùn)行結(jié)果為TextView的值為
"有新消息changed"
3.3谱秽、 Transformations.switchMap()
如果想要手動控制監(jiān)聽其中一個的數(shù)據(jù)變化洽蛀,并能根據(jù)需要隨時切換監(jiān)聽,這時可以使用Transformations.switchMap()弯院,它和Transformations.map()使用方式類似辱士,只不過switchMap()必須返回一個LiveData對象。
MediatorLiveData
是 LiveData
的子類听绳,允許您合并多個 LiveData 源。只要任何原始的 LiveData 源對象發(fā)生更改异赫,就會觸發(fā) MediatorLiveData
對象的觀察者椅挣。
例如,如果界面中有可以從本地數(shù)據(jù)庫或網(wǎng)絡(luò)更新的 LiveData
對象塔拳,則可以向 MediatorLiveData
對象添加以下源:
- 與存儲在數(shù)據(jù)庫中的數(shù)據(jù)關(guān)聯(lián)的
LiveData
對象鼠证。 - 與從網(wǎng)絡(luò)訪問的數(shù)據(jù)關(guān)聯(lián)的
LiveData
對象。
?
代碼如下所示:
class MergerLiveDataActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_merger)
val mutableLiveData1 = MutableLiveData<String>()
val mutableLiveData2 = MutableLiveData<String>()
val mutableLiveData3 = MutableLiveData<String>()
val liveDataMerger: MediatorLiveData<*> = MediatorLiveData<String>()
liveDataMerger.addSource(mutableLiveData1, object : Observer<String> {
override fun onChanged(t: String?) {
Log.d("TAG", "onChanged1:$t")
}
})
liveDataMerger.addSource(mutableLiveData2, object : Observer<String> {
override fun onChanged(t: String?) {
Log.d("TAG", "onChanged2:$t")
}
})
liveDataMerger.addSource(mutableLiveData3, object : Observer<String> {
override fun onChanged(t: String?) {
Log.d("TAG", "onChanged3:$t")
}
})
liveDataMerger.observe(this, Observer {
Log.d("TAG", "onChanged:$it");
})
mutableLiveData1.postValue("Onexzgj 的Jetpack")
mutableLiveData2.postValue("Onexzgj 的Jetpack2")
mutableLiveData3.postValue("Onexzgj 的Jetpack3")
}
}
為了更直觀的舉例靠抑,將LiveData和MediatorLiveData放到了同一個Activity中量九。通過MediatorLiveData的addSource將兩個MutableLiveData合并到一起,這樣當(dāng)任何一個MutableLiveData數(shù)據(jù)發(fā)生變化時,MediatorLiveData都可以感知到荠列。
打印結(jié)果如下类浪,任何一個liveData發(fā)生變化,liveDataMerger都會接受到通知
3.4肌似、擴(kuò)展LiveData對象
如果觀察者的生命周期出于STARTED或者RESUMED狀態(tài)费就,LiveData會將觀察者視為處于Active狀態(tài),關(guān)于如何擴(kuò)展LiveData,官網(wǎng)的例子比較簡潔川队,如下所示:
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager = StockManager(symbol)
private val listener = { price: BigDecimal ->
value = price
}
override fun onActive() {
stockManager.requestPriceUpdates(listener)
}
override fun onInactive() {
stockManager.removeUpdates(listener)
}
}
上面的代碼是一個觀察股票變動的一個例子力细,對LiveData進(jìn)行了拓展,實現(xiàn)了LiveData的兩個空方法onActive和onInactive固额。當(dāng)Active狀態(tài)的觀察者的數(shù)量從0變?yōu)?時會調(diào)用onActive方法眠蚂,通俗來講,就是當(dāng)LiveData對象具有Active狀態(tài)的觀察者時調(diào)用onActive方法斗躏,應(yīng)該在onActive方法中開始觀察股票價格的更新河狐。當(dāng)LiveData對象沒有任何Active狀態(tài)的觀察者時調(diào)用onInactive方法,在這個方法中瑟捣,斷開與StockManager服務(wù)的連接馋艺。
LiveData
對象具有生命周期感知能力,這一事實意味著您可以在多個 Activity迈套、Fragment 和 Service 之間共享它們捐祠。為使示例保持簡單,所以可以將 LiveData
類實現(xiàn)為單一實例桑李,如下所示:
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager: StockManager = StockManager(symbol)
private val listener = { price: BigDecimal ->
value = price
}
override fun onActive() {
stockManager.requestPriceUpdates(listener)
}
override fun onInactive() {
stockManager.removeUpdates(listener)
}
companion object {
private lateinit var sInstance: StockLiveData
@MainThread
fun get(symbol: String): StockLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
return sInstance
}
}
}
因此在Fragment中使用如下所示:
class MyFragment : Fragment() {
override fun onActivityCreated(savedInstanceState: Bundle?) {
StockLiveData.get(symbol).observe(this, Observer<BigDecimal> { price: BigDecimal? ->
// Update the UI.
})
}
多個 Fragment 和 Activity 可以觀察 MyPriceListener
實例踱蛀。僅當(dāng)一個或多個系統(tǒng)服務(wù)可見且處于活躍狀態(tài)時,LiveData 才會連接到該服務(wù)贵白。
四率拒、總結(jié)
這篇文章主要介紹了什么是LiveData,簡而言之可以理解為RxBus,以及LiveData的使用方法禁荒,這里沒有介紹LiveData
和ViewModel
的結(jié)合使用猬膨,以及LiveData的原理,這些會在后面的文章進(jìn)行介紹呛伴。
最后文章中涉及到的源碼及Jetpack的全組件均上傳至OnexZgj/Jetpack_Component