◾︎简介

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

这是官网上的一段话。意思就是 LiveData 的更新能够被 LifecycleOwner 所感知,但是前提是 LifecycleOwner 处于活跃状态。这样就有效的避免了更新 UI 时 Activity 已经不处于活跃而导致的崩溃。

本文代码使用 Kotlin 讲解,若需查看 Java 代码写法,请参考文末 Sample

◾︎添加依赖

LiveData 一般和 ViewModel 一起使用。

def lifecycle_version = "2.3.1"// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

◾︎使用

应当避免将 LiveData 直接存储在 Activity / Fragment 中,因为 Activity / Fragment 只负责 UI 显示,而不负责数据存储。

简单的使用 LiveData

  1. 在 ViewModel 中定义 LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModelclass NameViewModel : ViewModel() {val currentName: MutableLiveData<String> by lazy {MutableLiveData<String>()}
}
  1. 使用 LiveData 的 observe 方法
import androidx.lifecycle.ViewModelProviderviewModel = ViewModelProvider(this)[NameViewModel::class.java]
viewModel?.currentName?.observe(this, { name -> textView.text = name })

observe 方法有两个参数

  • 第一个是 LifecycleOwner 对象。这样 LiveData 就会感知 LifecycleOwner 的生命周期,只在 LifecycleOwner 活跃的时候才去调用第二个参数的 onChanged 方法
  • 第二个参数是 Observer 对象。Observer 是一个 interface,它的 onChanged 会在 LiveData 更新的时候被调用
  1. 更新 LiveData
viewModel?.currentName?.value = "更新 LiveData"

更新 LiveData 有两种方法

  • setValue。在主线程时使用 setValue
  • postValue。在子线程时使用 postValue,其实内部就是使用了 Handler 把值 post 到主线程去了。如果在主线程执行之前调用了多次 postValue,只有最后一次有效

LiveData vs MutableLiveData

LiveData 的 setValue 和 postValue 是 protected 的,只能在 ViewModel 内部使用。MutableLiveData 的 setValue 和 postValue 是 public 的,可以在任何地方使用。

自定义 LiveData

自定义一个监听网络状态的 LiveData

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.util.Log
import androidx.annotation.MainThread
import androidx.lifecycle.LiveDataclass NetworkLiveData(private val context: Context?) : LiveData<NetworkInfo?>() {private var networkReceiver: NetworkReceiverprivate var intentFilter: IntentFilterinit {networkReceiver = NetworkReceiver()intentFilter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)}companion object {private lateinit var instance: NetworkLiveData@MainThreadfun getInstance(context: Context?): NetworkLiveData {instance = if (::instance.isInitialized) instance else NetworkLiveData(context)return instance}}override fun onActive() {super.onActive()Log.d("tianjf", "onActive")context!!.applicationContext.registerReceiver(networkReceiver, intentFilter)}override fun onInactive() {super.onInactive()Log.d("tianjf", "onInactive")context!!.applicationContext.unregisterReceiver(networkReceiver)}inner class NetworkReceiver : BroadcastReceiver() {override fun onReceive(context: Context?, intent: Intent?) {val connectivityManager =context?.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManagerval networkInfo = connectivityManager?.activeNetworkInfogetInstance(context).value = networkInfo}}
}

自定义 LiveData 会覆写 onActive 和 onInactive 方法。它们会监听 LifecyclerOwner 的生命周期。当进入活跃状态(STARTED 或者 RESUMED)时,调用 onActive 方法,当进入非活跃状态时,调用 onInactive 方法。
在 onActivie 中注册广播,在 onInactive 中注销广播。这样代码就非常清晰明了了,网络状态的处理和 Activity/Fragment 分离开了。

转换 LiveData

转换会用到 Translations.map 和 Translations.switchMap
map、switchMap 和 RxJava 中的 map、flatMap 类似

Translations.map
val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = Transformations.map(userLiveData) {user -> "${user.name} ${user.lastName}"
}

当更新 userLiveData 的值时,会自动触发 userName 的 setValue 操作。其实就是对数据做 map 操作,转换为需要的格式。

Translations.switchMap
private fun getUser(id: String): LiveData<User> {...
}
val userId: LiveData<String> = ...
val user = Transformations.switchMap(userId) { id -> getUser(id) }

当设置 userId 的时候,会自动触发 getUser 操作并返回另一个 LiveData

MediatorLiveData

map 和 switchMap 的源码中都使用到了 MediatorLiveData。
从名称可以看出,MediatorLiveData 使用了终结者模式。
MediatorLiveData 可以接管普通的 LiveData,使得当 LiveData 有数据更新的时候,MediatorLiveData 也能够 “收到响应”。

private val originData = MutableLiveData<String>()
private val mediatorLiveData = MediatorLiveData<String>()mediatorLiveData.addSource(originData) { Log.i("tianjf", "originData: $it") }

MediatorLiveData 可以添加多个 LiveData

private val originData1 = MutableLiveData<String>()
private val originData2 = MutableLiveData<String>()
private val mediatorLiveData = MediatorLiveData<String>()mediatorLiveData.addSource(originData1) { mediatorLiveData.value = "originData: $it" }
mediatorLiveData.addSource(originData2) { mediatorLiveData.value = "originData: $it" }

observe 和 observeForever

observeForever 和 observe 的区别是,LifecyclerOwner 在非活跃状态下也会调用 Observer 的 onChanged 方法。
为了防止内存泄露,必须手动调用 removeObserver 方法

◾︎Sample

Kotlin 版
Java 版

Android Jetpack - LiveData相关推荐

  1. Android Jetpack LiveData 源码解析

    是什么 LiveData 是具备生命周期的数据,当数据放生变化的时候,如果页面已经销毁,那么就不会回调给监听者. 有什么用? 当我们获取到网络请求的数据,如果页面已经销毁了,就不会调用更新Ui 的方法 ...

  2. Android Jetpack组件之 LiveData使用-源码

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  3. Android Jetpack之DataBinding+ViewModel+LiveData+Room

    Android Jetpack之ViewModel.LiveData Android Jetpack之LifeCycle 前言 Jetpack是一个由多个技术库组成的套件,可帮助开发者遵循最佳做法,减 ...

  4. Android Jetpack Components of LiveData 学习笔记

    Android Jetpack Components of Lifecycle 学习笔记 Android Jetpack Components of LiveData 学习笔记 Android Jet ...

  5. Android Jetpack架构组件之 Room(使用、源码篇)

    2019独角兽企业重金招聘Python工程师标准>>> 1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发 ...

  6. Android Jetpack组件之Hilt使用

    前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. And ...

  7. Android Jetpack组件App Startup简析

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  8. Android Jetpack组件之WorkManger使用介绍

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  9. Android Jetpack组件之Navigation使用-源码

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

最新文章

  1. Android 第三方之MPAndroidChart
  2. 千万级、百万级数据删除优化
  3. [沪江日语电台]ACG杂货铺02-乱唱地带
  4. 数据挖掘中聚类算法概述
  5. 软件测试岗需要会什么条件,应聘软件测试岗位需要具备什么条件?
  6. μC/OS-III---I笔记3---时间管理
  7. python输入数据的维度_python – Keras LSTM输入维度设置
  8. 【错误】expected constructor, destructor, or type conversion before '.' token - 第八个游侠的日志 - 网易博客...
  9. 微信公众号全局返回码
  10. Bresenham直线插补算法
  11. [算法导论] 邮递员问题
  12. 从 SEC EDGAR 获取股东治理数据 (Shareholder Activism)
  13. 全球四大卫星导航系统年鉴
  14. (JAVA) 相邻数对
  15. 至联云课堂:隐私泄露屡禁不止,根本原因其实是...
  16. 数据集:人群行为识别数据库总结
  17. 杭州计算机职称考试培训,杭州全国职称英语等级考试强化培训班(综合类)
  18. 电子和计算机工程密歇根大学,美国密歇根大学迪尔本校区电子与计算机工程系主任 Yi Lu Murphey教授来我校进行学术交流并作学术报告...
  19. c语言冒泡排序法6,C语言的冒泡排序法
  20. [Android学习] 1. 简易登录界面设计

热门文章

  1. Maven-将jar包发布到本地maven仓库与私服
  2. 怎么让段落自动空两格_word自动空两格 如何设置word中段首自动空两格
  3. 【IPAVS】AV多媒体管理控制中心,AV媒体矩阵
  4. Jsp医院病区管理系统(论文+中期检查表+任务书+综合材料)
  5. SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation
  6. Yann LeCun主讲,纽约大学《深度学习》2021春季课程放出,免费可看
  7. 计算机主要键符的功能怎么读,计算机键盘中的全部按键基本功能.doc
  8. 电脑常用快捷键大全(含Visual Studio快捷键操作)
  9. word标题突然变成黑方框???
  10. 怎么把xml文件到url post方法 android,如何在android中使用http post发送xml文件.我把xml文件放在代码中...