当前位置: 首页 > news >正文

Android Jetpack系列组件之:LiveData(保姆级教程)

Android Jetpack系列组件之:LiveData(保姆级教程)

提示:建议新手多查阅官网资料,官网文档永远是第一手学习资料
官网链接:https://developer.android.com/topic/libraries/architecture/livedata?hl=zh-cn


LiveDate 保姆教程

  • Android Jetpack系列组件之:LiveData(保姆级教程)
    • @[TOC](LiveDate 保姆教程)
  • 前言
  • 一、LiveData 的优势
    • 1.确保界面符合数据状态
    • 2.避免发生内存泄漏
    • 3.不会因Activity停止而出现Crash问题
    • 4.不需要手动处理生命周期
    • 5.数据始终保持最新状态
    • 6.共享资源
  • 二、如何使用LiveData对象
    • 使用说明
  • 三、应用架构中的LiveData
  • 四、扩展LiveData
    • 单例模式
  • 五、转换LiveData

前言

什么是LiveData:及一种可观察的数据存储器类,LiveData具有生命周期感知能力,遵循其他应用组件(如activity、fragment或service)的生命周期
官网的概念进行如下解释:这个LiveData既是一个可以装数据的存储器,也是一个同四大组件的生命周期相互绑定的数据存储组件


一、LiveData 的优势

1.确保界面符合数据状态

LiveData遵循观察者模式,当底层数据发生变化时,LiveData会通知Observe对象,进而去Observe对象中更新UI操作,方便了开发者持续去监听数据的更新状态而更新UI

2.避免发生内存泄漏

观察者会绑定到LifeCycle对象,并关联其生命周期,随多绑定的对象的生命周期的销毁而进行自我清理

3.不会因Activity停止而出现Crash问题

如果观察者的生命周期处于非活跃状态(例如在返回堆栈中的Activity),它便不会接受任何LiveData时间

4.不需要手动处理生命周期

界面组件只是观察相关数据,不会停止或恢复观察,LiveData将自动管理所有这些操作,其在观察时可以感知相关的生命周期的状态变化(同第二条,与LifeCycle对象相绑定,关联其生命周期)

5.数据始终保持最新状态

如果生命周期变为非活跃状态,它会在再次变为活跃状态时接受最新的数据(如曾经在后台的Activity会在返回前台后立刻接受最新的数据)

6.共享资源

可以利用单例模式,扩展LiveData对象以封装相关系统服务,以便在应用中共享它们,LiveData对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察LiveData对象。(之后具体举例说明)

二、如何使用LiveData对象

使用说明

  • 在ViewModel中:创建LiveData的实例,用来存储某种数据类型的数据

  • 在Activity或fragment中:使用onChange() 或 observer() 方法,创建observer对象,用于观察当LiveData对象存储的数据发生变化时界面上的相应处理(更新UI等操作)

  • 大多数情况下,应用组件的onCreate() 方法 是开始观察 LiveData 对象的正确着手点

可以使用 observeForever(Observer) 方法 在没有关联的 LifecycleOwner 对象的情况下注册一个观察者。这种情况下,观察者始终处于活跃状态,因此始终可以收到关于修改的通知,手动调用 removeObserve(Observer) 方法 来移除这些观察者

//ViewModel 层 创建LiveData
class MyViewModel : ViewModel() {//实例化 LiveDataval myLiveData : MutableLiveData<String> by lazy {MutableLiveData<String>()}
}//应用组件层 使用&&更新 LiveData
class MyActivity : AppCompatActivity() {private val myViewModel : MyViewModel by viewModels()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)//开始观察LiveDataval myLiveDataObserver = Observer<String> { liveDate ->//取数据 用于更新页面UImyTextView.text = liveDate }//观察 LiveDatamyViewModel.myLiveData.observe(this, myLiveDataObserver)}//更新LiveData的数据private fun updateLiveData() {//比如UI层的点击实现,相应更新LiveData的操作...button.setOnClickLister {val changeData = "change Data"myViewModel.myLiveData.setValue(changeData)//在非主线程使用 postValue() }}
}

拓展思路(后续专栏详解):

  • 将LiveData与Room一起使用
  • 将协程与LiveData一起使用

三、应用架构中的LiveData

在架构层使用LiveData与其他组件间的使用规则:

  • LiveData具有生命周期感知能力,遵循Activity 和 Fragment 等实体的生命周期,使用LiveData 在这些生命周期所有者和生命周期不同的其他对象(如ViewModel对象)之间传递数据
  • ViewMode主要负责加载和管理与界面相关的数据,非常适合用于保留LiveData对象,及在ViewModel中创建LiveData对象,并向界面层公开出去
  • 在数据层类中使用LiveData,但注意LiveData不适用于处理异步数据流
  • LiveData与Kotlin Flow的组合使用
//在 Repository 中保留 LiveData 阻塞主线程
class MyRepository {fun getUser(): LiveData<List<User>> {...}fun getNewPrimiumUsers(): LiveData<List<User>> {return getUser().map { users ->users.filter { user ->user.isPremium}.filter { user ->val lastSyncedTime = dao.getLastSyncedTime()user.timeCreated > lastSyncedTime}}}}

四、扩展LiveData

若观察者的生命周期处于Started或者Resumed状态,LiveData会认为该观察者处于活跃状态

class MyLiveData(symbol: String) : LiveData<BigDecimal>() {private val dataManager = DataManager(symbol)private val listener = { price: BigDecimal ->value = price}//当LiveData 对象具有活跃观察者时,会调用onActive() 方法override fun onActive() {dataManager.requestPriceUpdates(listener)}//当LiveData 对象没有任何活跃观察者时,会调用onInactive() 方法override fun onInactive() {dataManager.removeUpdates(listener)}
}//使用MyLiveData类
public class MyFragment : Fragment() {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)val myPriceListener: LiveData<BigDecimal> = ...myPriceListener.observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? ->//update the UI}) }
}

单例模式

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 onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)StockLiveData.get(symbol).observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? ->// Update the UI.})}
  • 多个 fragment 和 activity 可以观察 MyPriceListener 实例。仅当一个或多项系统服务可见且处于活跃状态时,LiveData 才会连接到该服务。

五、转换LiveData

需求场景:希望将LiveData 对象分配给观察者之前对存储在其中的值进行更改,或者需要根据另一个实例的值返回不同的LiveData实例,Lifecycle提供Transfromations类来进行相关处理

//对存储在LiveData对象中的值应用函数 并将该结果传播到下游
val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<Strring> = userLiveData.map {user-> "${user,name} ${user.lastName}"
}//与map类似,将存储在LiveData对象中的值应用函数,并将结果解封和分派到下游,传递给switchMap()的函数必须返回LiveData对象
private fun getUser(id: String): LiveData<User> {...
}
val userId: LiveData<Strng> = ...
val user = userId.switchMap { id-> getUser(id) }
http://www.lryc.cn/news/595134.html

相关文章:

  • 动静态库原理与实战详解
  • Ubuntu 22 安装 ZooKeeper 3.9.3 记录
  • 【HarmonyOS】ArkUI - 声明式开发范式
  • 信息整合注意力IIA,通过双方向的轻量级注意力机制强化目标关键特征并抑制噪声,提升特征融合的有效性和空间位置信息的保留能力。
  • I2S音频的时钟
  • C/C++ 详谈结构体大小计算(内存对齐)
  • 移动端轻量级神经网络推理框架
  • 蚂蚁数科AI数据产业基地正式投产,携手苏州推进AI产业落地
  • 解决mac chrome无法打开本地网络中的内网网址的问题
  • ELN和LIMS的区别
  • Django关于ListView通用视图的理解(Cursor解释)
  • Java基础教程(010):面向对象中的this和就近原则
  • 算法训练营DAY37 第九章 动态规划 part05
  • 两个相机的视野 拼接算法
  • 【C++】stack和queue拓展学习
  • DevCon 6记录
  • 从 “能用“ 到 “好用“:中小制造企业数字化转型中的 IT 系统优化管理策略
  • 扬声器测试解决方案
  • AWS Certified Cloud Practitioner 认证考试总结
  • Centos安装最新docker以及ubuntu安装docker
  • 旋转目标检测(Rotated Object Detection)技术概述
  • ESP32-S3学习笔记<1>:ESP-IDF的安装与命令
  • 【编程语言】C、C++、C#深度对比:三种语言的演进历程与应用场景
  • Windows VS2019 编译 Apache Thrift 0.15.0
  • 倒排索引实操
  • CS231n-2017 Lecture4神经网络笔记
  • selenium爬取图书信息
  • 通信刚需小能手,devicenet转PROFINET网关兼容物流分拣自动化
  • 从cv610的demo原理看,i2c的上拉电阻为 1k
  • day27 力扣332.重新安排行程 力扣51. N皇后 力扣37. 解数独 力扣455.分发饼干 力扣376. 摆动序列 力扣53. 最大子序和