写点什么

Jetpack- 在数据变化时如何优雅更新 Views 数据

用户头像
Android架构
关注
发布于: 5 小时前

创建 观察 LiveData 的对象

有了数据源之后,总需要有观察者来观察数据源,不然数据源就失去了存在的意义。


那么在哪里观察数据源呢?


在大多数情况下,在应用组件的onCreate()方法


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


中访问 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 会认为订阅者的生命周期处于STARTEDRESUMED状态时,该订阅者是活跃的。


那么如何使用 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


@MainThreadfun 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.})


}

转换 LiveData

有时候在把数据分发给 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> {...}

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Jetpack-在数据变化时如何优雅更新Views数据