前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Jetpack:在数据变化时如何优雅更新Views数据

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

作者头像
Android技术干货分享
发布于 2019-07-02 10:08:31
发布于 2019-07-02 10:08:31
3K00
代码可运行
举报
文章被收录于专栏:Android技术分享Android技术分享
运行总次数:0
代码可运行
又到周末好时光,茫茫人海中,与你在掘金相遇,好幸运~请君赏阅本文,相处不易,开门见山,不扯皮。本文讲的是关于Jetpack的架构组件LiveData,LiveData是Lifecycle-aware 组件的一个应用,这意味着LiveData遵守Activity、Fragment和Service等组件的生命周期,在它们生命周期处于活跃状态(CREATEDRESUMED)才进行更新Views。

使用LiveData步骤

  1. 创建持有某种类型的LiveData对象。通常在ViewModel类来实现该对象。
  2. 定义一个具有onChanged()方法的Observer对象,当LiveData持有数据变化是回调该方法。通常在UI控制器类中实现创建该Observer对象,如Activity或Fragment。
  3. 通过使用observe()方法,将上述的LiveData对象和Observer对象关联在一起。这样Observer对象就与LiveData产生了订阅关系,当LiveData数据发生变化时通知,而在Observer更新数据,所以Observer通常是Activity和Fragment。

三个步骤就定义了使用LiveData的方式,从步骤可以看出,使用了观察者模式,当LiveData对象持有数据发生变化,会通知对它订阅的所有处于活跃状态的订阅者。而这些订阅者通常是UI控制器,如Activity或Fragment,以能在被通知时,自动去更新Views。

创建LiveData对象

LiveData可以包装任何数据,包括集合对象。LiveData通常存储在ViewModel中,并通过getter方法获得。示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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中呢?

  • 这样导致Activity或Fragment代码臃肿,Activity或Fragment一般用来展示数据而不是持有数据。
  • 将LiveData解耦,不和特定的Activity或Fragment绑定在一起。

创建 观察LiveData 的对象

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

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

在大多数情况下,在应用组件的onCreate()方法中访问LiveData是个合适的时机。这样可以确保系统不在Activity或Fragment的onResume()方法进行多余的调用;另外这样也确保Activity和Fragment尽早有数据可以进行显示。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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中的视图。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
button.setOnClickListener {
    val anotherName = "GitCode"
    model.currentName.setValue(anotherName)
}

当单击button时,字符串GitCode会存储到LiveData中,nameTextView的文本也会更新为GitCode。这里通过button的点击来给LiveData设置值,也可以网络或者本地数据库获取数据方式来设置值。

扩展 LiveData

可以通过下面的栗子来看看如何扩展LiveData。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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中使用,所以可以创建单例模式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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可以这样使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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()方法可以改变其下游的结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
    user.name + " " + user.lastName
});

使用Transformations.switchMap()同样可以改变下游的结果,但传递给switchMap()的函数必须返回一个LiveData对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private fun getUser(id: String): LiveData<User> {
  ...
}
val userId: LiveData<String> = ...
val user = Transformations.switchMap(userId) { id -> getUser(id) }

这种转换方式都惰性的,也就是只有Observer来订阅数据的时候,才会进行转换。当在ViewModel需要一个Lifecycle对象,或许这种转换会是很好的解决方案。

合并多个LiveData 源

MediatorLiveData是LiveData的子类,它主要用途是用来合并多个LiveData源。当其中一个源数据发生变化是,都会回调订阅MediatorLiveData的观察者的onChanged()方法。例如我们在实际开发中,我们的数据源要么来自服务器,要么来自本地数据库。这里就考虑使用MediatorLiveData。

更多信息请参阅官网

总结

LiveData的入门使用来说还是相对简单的,等到后面讲完Jetpack系列文章,再以一个综合的Demo示例Jetpack涉及到的一些知识点。光看文档,都可以感觉到Android 对设计模式,和MVP模式、MVVM模式设计理念使用得淋漓尽致。所以建议各位同学在代码方面的编写一定要有大局观念,代码规范的还是要有,方便别人就是方便自己。不要为应付功能实现而代码臃肿,后续又不重新架构,一直积累成垃圾码。

最后

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.06.29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
AAC---LiveData
LiveData是一个与Activity/Fragment生命周期相关(lifecycle-aware)的Observer类。而这种相关性(awareness )会导致LiveData中的数据只有在Active状态下才会被回调。
None_Ling
2018/10/24
1.1K0
Jetpack—LiveData组件的缺陷以及应对策略
为了解决Android-App开发以来一直存在的架构设计混乱的问题,谷歌推出了Jetpack-MVVM的全家桶解决方案。作为整个解决方案的核心-LiveData,以其生命周期安全,内存安全等优点,甚至有逐步取代EventBus,RxJava作为Android端状态分发组件的趋势。
2020labs小助手
2022/01/19
1.2K0
Kotlin 和 JetPack 的项目实战(一)
从谷歌在 2017 年的 Google IO 宣布 Kotlin 成为 Android 开发的官方语言开始,已经过去将近 2 年了,Kotlin 越来越被开发者所关注,在 Github 的开源项目中使用这门语言的也呈上升趋势。
爱因斯坦福
2019/02/27
1K0
Kotlin 和 JetPack 的项目实战(一)
livedatabus详解,阿里是如何用他来做淘宝架构的?
Google 为了帮助 Android 开发者更快更好地开发 App,推出了一系列组件,这些组件被打包成了一个整体,称作 Android Jetpack,它包含的组件如下图所示:
Android技术干货分享
2019/05/15
1.2K0
livedatabus详解,阿里是如何用他来做淘宝架构的?
“终于懂了“系列:Jetpack AAC完整解析(二)LiveData 完全掌握!
也就是说,LiveData使得 数据的更新 能以观察者模式 被observer感知,且此感知只发生在 LifecycleOwner的活跃生命周期状态。
胡飞洋
2020/12/15
4K0
Android Jetpack架构组件(四)之LiveData
LiveData是Jetpack架构组件Lifecycle 库的一部分,是一个可感知生命周期的可观察容器类 (Observable)。与常规的可观察类不同,LiveData 具有生命周期感知能力,这意味着它具有感知应用组件(如 Activity、Fragment 或 Service)的生命周期的能力,并且LiveData仅更新处于活跃生命周期状态的应用组件观察者。
xiangzhihong
2020/12/21
3.4K0
Android从零开始搭建MVVM架构(4)——LiveData
Livedata 是 Google 推荐的 Android 架构组件之一,是一个存放可被观察的数据持有类,有生命周期感知功能,解决了android开发者需要去手动处理生命周期的痛点。 比如当我们使用 Retrofit+Rxjava处理接口回调数据时,需要考虑activity 或 fragment 生命周期,以解决 onStop 或 onDestory之后回调数据的问题。现在只需要 Retrofit+Livedata 就好,其他的 Livedata 帮你做了。
老马的编程之旅
2022/06/22
2.4K0
Android Architecture Components Part2:LiveData
感谢你的再次光临,欢迎来到Android Architecture Components(AAC)系列文章。上篇文章我们一起讨论了Room,通过Room我们能够方便的操作App的数据库。如果你的App对本地数据库有所依赖的话,Room你值得拥有。
Rouse
2019/07/16
5620
ViewModels and LiveData- Patterns + AntiPatterns
这个系列我做了协程和Flow开发者的一系列文章的翻译,旨在了解当前协程、Flow、LiveData这样设计的原因,从设计者的角度,发现他们的问题,以及如何解决这些问题,pls enjoy it。
用户1907613
2021/12/13
1.2K0
ViewModels and LiveData- Patterns + AntiPatterns
AndroidJetpack Livedata应用场景分析
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力
用户9239674
2021/11/29
1.1K0
Jetpack组件之LiveData
ViewModel 以注重生命周期的方式存储和管理界面相关的数据,当数据发生变化时,可通过接口的方式通知页面,但是有很多数据要通知时,需要定义大量的接口显得十分冗余,为此,Jetpack提供了LiveData组件解决这种问题,简化了开发过程。 LiveData 是一种可观察的数据存储器类。它是一个数据的容器,将数据包装起来,使数据成为被观察者,当数据发生变化时,观察者能够获得通知。 LiveData 具有生命周期感知能力,它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
八归少年
2022/06/29
8440
Android Jetpack - LiveData
LiveData 是一个可观察数据包装类,与普通观察者不同,LiveData 具备生命周期感知能力,这意味着它遵循其它应用组件的生命周期(Activity、Fragment、Service 等),此感知能力确保了 LiveData 只更新处于生命周期活跃状态的组件的观察者
SkyRiN
2019/08/12
2K0
LiveData奇思妙用总结
一个全局计数器,Activity销毁时,计时器停止,不会导致内存泄露,Activity激活时,计时器开始,自动获取最新的计时。
没关系再继续努力
2021/12/07
6000
LiveData beyond the ViewModel
这个系列我做了协程和Flow开发者的一系列文章的翻译,旨在了解当前协程、Flow、LiveData这样设计的原因,从设计者的角度,发现他们的问题,以及如何解决这些问题,pls enjoy it。
用户1907613
2021/12/08
1.5K0
LiveData beyond the ViewModel
4. Jetpack源码解析—LiveData的使用及工作原理
2. Jetpack源码解析—Navigation为什么切换Fragment会重绘?
Hankkin
2019/07/10
1K0
Jetpack之LiveData详解
LiveData 是Jetpack中的一个组件,是一个可被观察的数据存储器类, 具有感知组件生命周期的能力,LiveData 可以感知组件生命周期活跃状态发送数据更新,在组件销毁时移除观察者对象,大多结合具有生命周期的组件一起使用(如 Activity、Fragment 或 Service,或实现了 LifecycleOwner 接口的对象)。
loongwind
2022/09/22
1.7K0
Jetpack之LiveData详解
谷歌官方Android应用架构库——LiveData
LiveData 是一个数据持有者类,它持有一个值并允许观察该值。不同于普通的可观察者,LiveData 遵守应用程序组件的生命周期,以便 Observer 可以指定一个其应该遵守的 Lifecycle。
Anymarvel
2018/10/22
1.1K0
Android技术栈(四)Android Jetpack MVVM 完全实践
本文包含Android中MVVM体系中的很多部分,主要对ViewModel+DataBinding+RxJava+LiveData+Lifecycle等笔者所使用的技术体系进行解析.
Android技术干货分享
2019/04/18
3.9K0
Android技术栈(四)Android Jetpack MVVM 完全实践
Android 面试题:为什么 Activity 都重建了 ViewModel 还存在?—— Jetpack 系列(3)
ViewModel 是 Jetpack 组件中较常用的组件之一,也是实现 MVVM 模式或 MVI 模式的标准组件之一。在这篇文章里,我将与你讨论 ViewModel 实用和面试常见的知识点。如果能帮上忙请务必点赞加关注,这对我非常重要。
用户9995743
2022/09/26
1.2K0
Android 面试题:为什么 Activity 都重建了 ViewModel 还存在?—— Jetpack 系列(3)
是时候更新手里的武器了—Jetpack架构组件简析
最近两年,MVVM的呼声越来越高,说实话,在经历了MVP的臃肿,MVP的繁琐,我有点怕了。但是这次Google官方带来的一系列为MVVM架构设计的武器—Jetpack,真的让我惊喜到了。
码上积木
2020/09/27
2.9K0
相关推荐
AAC---LiveData
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文