LiveData是Android Jetpack裏的一個組件庫,它具備感知activity和fragment生命週期的功能,使用觀察者模式設置數據並確保數據在activity和fragment正確的生命週期內更新ui,提高app性能,並防止app crashjava
先來看一個很是簡單的例子android
class LiveDataActivity : AppCompatActivity() {
var liveData: MutableLiveData<String>? = null
var disposable: Disposable? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_livedata)
liveData = MutableLiveData()
// 觀察數據的變化,只有在界面可見的時候纔會回調(即onStart或onResume狀態)
liveData!!.observe(this, Observer {
tv_text.text = it
})
loadData()
}
override fun onDestroy() {
super.onDestroy()
disposable?.dispose()
}
private fun loadData() {
disposable = Flowable.interval(1, 1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
// 更新數據
liveData?.value = it.toString()
}
}
}
複製代碼
LiveData
的用法很是簡單,首選new一個LiveData
對象,而後經過observe
方法添加一個Observer
,並實現Observer
接口的onChanged
方法,最後在數據更新的時候使用livedata
的setValue
方法更新數據便可;調用setValue
方法的時候,若是當前Activity
處於onStart
或onResume
狀態,則會調用Observer
的onChanged
回調,不然先緩存數據,當Activity
從新回到onStart
或onResume
狀態時,再調用Observer
的onChanged
回調(Activity
destroy時 會自動remove Observer
,因此不須要咱們手動remove)git
setValue(T value)github
必須在 UI Thread 中調用,更新數據,同時當Activity
處於onStart
或onResume
狀態時會調用Observer
的onChanged
回調數據庫
postValue(T value)緩存
跟setValue()同樣,惟一的區別就是能夠 非UI Thread 中調用,而後經過handler post在UI Thread中回調網絡
observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)app
這是一個很是經常使用的方法, 用於添加一個Observer,監聽數據的變化; LifecycleOwner 通常是activity 或 fragment對象,使其LiveData能夠感知其生命週期,只有在onStart
或onResume
狀態時會調用Observer
的onChanged
回調, 在destroy
時 remove Observer
異步
observeForever(@NonNull Observer<? super T> observer)ide
跟observe方法差很少,惟一的區別是沒辦法感知activity 或 fragment生命週期;即只要有數據更新就立馬調用Observer
的onChanged
回調,而且須要手動remove Observer
;這個方法對於Transformation
(數據轉換)很是有用,下面會介紹到
removeObservers(@NonNull final Observer<? super T> observer)
這個方法很簡單,就是刪除某個observer
onActive()
這是LiveData的一個回調方法,當observer的數量由0變成1的時候,會調用
onInactive()
這是LiveData的一個回調方法,當observer的數量由1變成0的時候,會調用
MutableLiveData 比較簡單,通常沒什麼特殊需求,用MutableLiveData就能夠,他的源碼實現也很是簡單
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
複製代碼
只是將LiveData
用protected
修飾postValue
和setValue
的方法改爲了public
用法就跟上面的demo
同樣
MediatorLiveData
繼承MutableLiveData
, 並提供addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged)
方法監聽LiveData
的數據更新,而後作一層處理或直接通知給最外層的Observer
先看一下源碼裏的example, 只處理前10次數據的變化
LiveData<String> liveData1 = ...;
var liveDataMerger = MediatorLiveData<String>()
liveDataMerger.addSource(liveData1, object: Observer<String> {
var count = 1
override fun onChanged(t: String) {
count++
// 在這裏更新liveDataMerger的數據;所以能夠在這裏對數據作一些額外的處理以後再更新
liveDataMerger.value = t
if (count > 10) {
liveDataMerger.removeSource(liveData1)
}
}
})
複製代碼
同時它還能夠監聽多個LiveData
的變化
val liveData1 = MutableLiveData<String>()
val liveData2 = MutableLiveData<String>()
var liveDataMerger = MediatorLiveData<String>()
liveDataMerger.addSource(liveData1, Observer { liveDataMerger.value = it })
liveDataMerger.addSource(liveData2, Observer { liveDataMerger.value = it })
// 只要liveData1和liveData2數據有更新就會通知Observer更新ui
liveDataMerger.observe(this, Observer {
tv_text.text = it
})
複製代碼
其實MediatorLiveData最經常使用的用法是結合Transformation來使用,下面將介紹Transformation的用法
Transformation
內部原理使用MediatorLiveData
實現的
有的時候咱們須要對當前data 轉換成咱們須要的另外一種data
好比rxjava
的map
方法
Flowable.range(1, 10)
.map { "index: $it" }
.subscribe {
}
複製代碼
再好比 kotlin
自帶的map
擴展方法
val list = listOf(1, 2, 3, 4).map {
"index: $it"
}
複製代碼
LiveData
也提供了相似的map
功能
// 建立LiveData
val userLiveData: LiveData<User> = MutableLiveData<User>()
val userName: LiveData<String> = Transformations.map(userLiveData) {
user -> "${user.name} ${user.lastName}"
}
//觀察數據的更新
userName.observe(this, Observer {
tv_text.text = it
})
...
// 更新數據
userLiveData.value = User("zhang", "san")
複製代碼
LiveData
也提供了switchMap
方法轉換數據,它與map
惟一的不一樣是將data
轉換成一個LiveData<T>
,所以在轉換過程當中能夠繼續作異步操做請求數據等,他跟rxjava
的flatmap
方法有點像
// 先使用room數據庫定義一個UserDao example
@Dao
abstract class UserDao {
@Query("select * from tab_user where uid = :uid")
abstract fun getById(uid: Long): LiveData<User>
}
...
private fun getUser(id: String): LiveData<User> {
// 可使用room數據查詢user對象
// return AppDataBase.getUserDao().getUser(id)
// 你也能夠髮網絡請求查詢user對象
return object: LiveData<User>() {
override fun onActive() {
super.onActive()
// 模擬網絡請求數據
Flowable.timer(3, TimeUnit.SECONDS)
.subscribe {
postValue(User("zhang", "san"))
}
}
}
}
...
val userId: LiveData<String> = MutableLiveData<String>()
val user = Transformations.switchMap(userId) { id -> getUser(id) }
//觀察數據的更新
user.observe(this, Observer {
tv_text.text = "${it.name} ${it.name}"
})
...
// 更新數據
userId.value = "001"
複製代碼
LiveData使用起來比較簡單,功能就介紹到這裏,建議查看一下官方demo 學習結合其它library的用法