Jetpack- 在数据变化时如何优雅更新 Views 数据,ffmpeg 音视频开发实战 6 下载
LiveData 可以包装任何数据,包括集合对象。LiveData 通常存储在 ViewM
odel 中,并通过 getter 方法获得。示例:
class NameViewModel : ViewModel() {
// Create a LiveData with a Stringval currentName: MutableLiveData<String> by lazy {MutableLiveData<String>()}
// Rest of the ViewModel...}
为什么是 ViewModel 持有 LiveData 而不是 Activity 或者 Fragment 中呢?
这样导致 Activity 或 Fragment 代码臃肿,Activity 或 Fragment 一般用来展示数据而不是持有数据。
将 LiveData 解耦,不和特定的 Activity 或 Fragment 绑定在一起。
创建 观察 LiveData 的对象
有了数据源之后,总需要有观察者来观察数据源,不然数据源就失去了存在的意义。
那么在哪里观察数据源呢?
在大多数情况下,在应用组件的onCreate()
方法中访问 LiveData 是个合适的时机。这样可以确保系统不在 Activity 或 Fragment 的onResume()
方法进行多余的调用;另外这样也确保 Activity 和 Fragment 尽早有数据可以进行显示。
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 本身没有提供公共方法更新值。如果需要修改 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
可以通过下面的栗子来看看如何扩展 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,并重写两个重要方法。
onActivite() 当有活跃状态的订阅者订阅 LiveData 时会回调该方法。意味着需要在这里监听数据的变化。
onInactive() 当没有活跃状态的订阅者订阅 LiveData 时会回调该方法。此时没有必要保持 StockManage 服务象的连接。
setValue() 注意到
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
评论