又到周末好时光,茫茫人海中,与你在掘金相遇,好幸运~请君赏阅本文,相处不易,开门见山,不扯皮。本文讲的是Jetpack系列第三个架构组件LiveData,LiveData是Lifecycle-aware 组件的一个应用,这意味着LiveData遵照Activity、Fragment和Service等组件的生命周期,在它们生命周期处于活跃状态(CREATED
和RESUMED
)才进行更新Views。java
三个步骤就定义了使用LiveData的方式,从步骤能够看出,使用了观察者模式,当LiveData对象持有数据发生变化,会通知对它订阅的全部处于活跃状态的订阅者。而这些订阅者一般是UI控制器,如Activity或Fragment,以能在被通知时,自动去更新Views。android
LiveData能够包装任何数据,包括集合对象。LiveData一般存储在ViewModel中,并经过getter方法得到。示例:git
class NameViewModel : ViewModel() {
// Create a LiveData with a String
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
// Rest of the ViewModel...
}
复制代码
为何是ViewModel持有LiveData而不是Activity或者Fragment中呢?github
有了数据源以后,总须要有观察者来观察数据源,否则数据源就失去了存在的意义。数据库
那么在哪里观察数据源呢?设计模式
在大多数状况下,在应用组件的onCreate()
方法中访问LiveData是个合适的时机。这样能够确保系统不在Activity或Fragment的onResume()
方法进行多余的调用;另外这样也确保Activity和Fragment尽早有数据能够进行显示。bash
class NameActivity : AppCompatActivity() {
private lateinit var model: NameViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Other code to setup the activity...
// Get the ViewModel.
model = ViewModelProviders.of(this).get(NameViewModel::class.java)
// Create the observer which updates the UI.
val nameObserver = Observer<String> { newName ->
// Update the UI, in this case, a TextView.
nameTextView.text = newName
}
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.currentName.observe(this, nameObserver)
}
}
复制代码
在讲nameObserver对象传给observe()方法后,存储在LiveData最近的值以参数的形式当即传递到onChange()方法中。固然,若是此时LiveData没有存储值的话,onChange()
方法不会被调用。服务器
LiveData自己没有提供公共方法更新值。若是须要修改LiveData的数据的话,能够经过MutableLiveData来暴露共有方法setValue()
和postValue()
。一般在在ViewModel中使用MutableLiveData,而MutableLiveData暴露不可变的LiveData给Observer。与Observer创建关系后,经过修改LiveData的值从而更新Observer中的视图。网络
button.setOnClickListener {
val anotherName = "GitCode"
model.currentName.setValue(anotherName)
}
复制代码
当单击button时,字符串GitCode
会存储到LiveData中,nameTextView的文本也会更新为GitCode
。这里经过button的点击来给LiveData设置值,也能够网络或者本地数据库获取数据方式来设置值。架构
能够经过下面的栗子来看看如何扩展LiveData。
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)
}
}
复制代码
首先创建一个StockLiveData并继承自LiveData,并重写两个重要方法。
value=price
这里是调用了setValue(price)方法,经过该方法更新LiveData的值,进而通知处于活跃状态的订阅者。LiveData会认为订阅者的生命周期处于STARTED
或RESUMED
状态时,该订阅者是活跃的。
那么如何使用StockLiveData呢?
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val myPriceListener: LiveData<BigDecimal> = ...
myPriceListener.observe(this, Observer<BigDecimal> { price: BigDecimal? ->
// Update the UI.
})
}
复制代码
以Fragment做LifecycleOwner的实例传递到observer()方法中,这样就将Observer绑定到拥有生命周期的拥有者。因为LiveData能够在多个Activity、Fragment和Service中使用,因此能够建立单例模式。
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.
})
}
复制代码
有时候在把数据分发给Observer前,转换存储在LiveData中的值,或者返回一个 基于已有值的LiveData对象 的另一个LiveData对象。这时候就须要用到 Transformations类来处理了。
使用Transformations.map()
方法能够改变其下游的结果:
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
user.name + " " + user.lastName
});
复制代码
使用Transformations.switchMap()一样能够改变下游的结果,但传递给switchMap()的函数必须返回一个LiveData对象。
private fun getUser(id: String): LiveData<User> {
...
}
val userId: LiveData<String> = ...
val user = Transformations.switchMap(userId) { id -> getUser(id) }
复制代码
这种转换方式都惰性的,也就是只有Observer来订阅数据的时候,才会进行转换。当在ViewModel须要一个Lifecycle对象,或许这种转换会是很好的解决方案。
MediatorLiveData是LiveData的子类,它主要用途是用来合并多个LiveData源。当其中一个源数据发生变化是,都会回调订阅MediatorLiveData的观察者的onChanged()
方法。例如咱们在实际开发中,咱们的数据源要么来自服务器,要么来自本地数据库。这里就考虑使用MediatorLiveData。
LiveData的入门使用来讲仍是相对简单的,等到后面讲完Jetpack系列文章,再以一个综合的Demo示例Jetpack涉及到的一些知识点。光看文档,均可以感受到Android 对设计模式,和MVP模式、MVVM模式设计理念使用得淋漓尽致。因此建议各位同窗在代码方面的编写必定要有大局观念,代码规范的仍是要有,方便别人就是方便本身。不要为应付功能实现而代码臃肿,后续又不从新架构,一直积累成垃圾码。
本文是Jetpack系列文章第三篇
第一篇: Jetpack:你还在findViewById么?
第二篇:Jetpack:你如何管理Activity和Fragment的生命周期?