Android APP开发中,开发者们都想有一个公共的组件,可以实现后台数据的监听,同时实时更新到UI进行显示,从而大大简化开发过程。Google针对这一开发需求,提供了Jetpack LiveData组件。下面我们来一起看下LiveData的基本使用方法吧!

首先,先了解下使用LiveData的优点。

  • 确保UI与数据状态匹配

  • 不需要担心内存泄漏问题

  • Activity停止后数据变化不会导致Crash

  • 不再需要人工生命周期的处理

  • 始终使用最新的数据

  • 正确应用配置更改

  • 共享资源

LiveData遵循观察者模式,实现LifeCycle接口,因此可以监听数据的实时更新,感知应用的生命周期,让开发者能够更多的关注业务具体实现。

下面我们来通过一个小Demo来简单介绍下LiveData的基本使用方法。

![file](https://img2018.cnblogs.com/blog/1820853/201909/1820853-20190930133422041-186307834.gif)

本例中,数据变化通知UI的显示由四个控件体现,分别为:系统时间(Long型)、系统时间、天气、远端数据。针对这四个控件的动态显示,我们分别来看下其是如何实现的。

框架搭建

APP首先需要搭建使用LiveData的环境:

1. 导入依赖包

//app build.gradle
dependencies {
...
implementation deps.lifecycle.viewmodel_ktx
implementation deps.lifecycle.livedata_ktx
...
}

## 2. 创建ViewModel类(用于LiveData数据的封装,和UI交互)

```
class LiveDataViewModel(
private val dataSource: DataSource
) : ViewModel() {...}
```

## 3. 布局文件中引用ViewModel对象

 <layout>
<data>
<variable
name="viewmodel"
type="com.android.example.livedatabuilder.LiveDataViewModel" />
</data>
...
</layout>

## 4. Activity绑定ViewModel

```
//MainActivity
//成员变量
private val viewmodel: LiveDataViewModel by viewModels { LiveDataVMFactory }
//onCreate
val binding = DataBindingUtil.setContentView(
this, R.layout.activity_livedata
)
// Set the LifecycleOwner to be able to observe LiveData objects
binding.lifecycleOwner = this

// Bind ViewModel

binding.viewmodel = viewmodel

//LifeDataVMFactory

object LiveDataVMFactory : ViewModelProvider.Factory {

private val dataSource = DefaultDataSource(Dispatchers.IO)

override fun <T : ViewModel?> create(modelClass: Class): T {

@Suppress("UNCHECKED_CAST")

return LiveDataViewModel(dataSource) as T

}

}

<br/>
### 注意:此处构造ViewModel采用的dataSource为DefaultDataSource,后续数据是根据此数据源来进行获取的。
<br/>
# 系统时间(Long型)显示
<br/>
系统时间的显示,通过在UI上绑定ViewModel,通过getCurrentTime方法后台更新、提交数据,来通知UI进行显示的更新。
<br/>

//xml

<TextView

android:id="@+id/time"

android:text="@{Long.toString(viewmodel.currentTime)}"

.../>

//LiveDataViewModel

val currentTime = dataSource.getCurrentTime()

//DefaultDataSource

override fun getCurrentTime(): LiveData =

liveData {

while (true) {

emit(System.currentTimeMillis())//通知当前系统时间

delay(1000)//延时1秒

}

}

<br/>
# 系统时间显示
<br/>
系统时间的显示是根据系统获取的Long型变量变化映射得到的,Long值发生变化时,实时更新系统时间显示。
<br/>

//xml

<TextView

android:id="@+id/time_transformed"

android:text="@{viewmodel.currentTimeTransformed}"

.../>

//LiveDataViewModel 此处有两种方式实现

//1. currentTime变更后实时通知UI更新

val currentTimeTransformed : LiveData = Transformations.map(currentTime) {

Date(it).toString()

}

//2. 延时500ms后通知

val currentTimeTransformed = currentTime.switchMap {

// timeStampToTime is a suspend function so we need to call it from a coroutine.

liveData { emit(timeStampToTime(it)) }

}

private suspend fun timeStampToTime(timestamp: Long): String {

delay(500) // Simulate long operation

val date = Date(timestamp)

return date.toString()

}

<br/>
# 天气显示
<br/>
天气的显示通过动态改变数据源提供的数据,从而通知UI显示(DataSource数据的更新实时通过LiveData传递到UI)。
<br/>

//xml

<TextView

android:id="@+id/current_weather"

android:text="@{viewmodel.currentWeather}"

.../>

//LiveDataViewModel

val currentWeather: LiveData = liveData {

emit(LOADING_STRING)

emitSource(dataSource.fetchWeather())

}

//DefaultDataSource

private val weatherConditions = listOf("Sunny", "Cloudy", "Rainy", "Stormy", "Snowy")

override fun fetchWeather(): LiveData = liveData {

var counter = 0

while (true) {

counter++

delay(2000)//延时两秒

//按顺序循环显示weatherConditions中的天气数据信息

emit(weatherConditions[counter % weatherConditions.size])

}

}

<br/>
# 远端数据显示
<br/>
远端数据的请求通过Button的点击事件触发,数据获取成功后,通知TextView进行数据显示。
<br/>

//xml

<TextView

android:id="@+id/cached_value"

android:text="@{viewmodel.cachedValue}"

.../>

<Button

android:id="@+id/refresh_button"

android:onClick="@{() -> viewmodel.onRefresh()}"

.../>

//LiveDataViewModel

val cachedValue = dataSource.cachedData

fun onRefresh() {

// Launch a coroutine that reads from a remote data source and updates cache

viewModelScope.launch {

dataSource.fetchNewData()

}

}

//DefaultDataSource

private val _cachedData = MutableLiveData("This is old data")

override val cachedData: LiveData = _cachedData

override suspend fun fetchNewData() {

// Force Main thread

withContext(Dispatchers.Main) {

_cachedData.value = "Fetching new data..."

_cachedData.value = simulateNetworkDataFetch()

}

}

private var counter = 0

// Using ioDispatcher because the function simulates a long and expensive operation.

private suspend fun simulateNetworkDataFetch(): String = withContext(ioDispatcher) {

delay(3000)//延时3秒

counter++

"New data from request #$counter"//返回此字符串

}

<br/>
##### 小提示:本例中的viewModelScope使用的是Kotlin Coroutines(协程)功能,更多协程使用方法,请查看Coroutines在架构组件中的应用:[官方文档链接](https://developer.android.google.cn/topic/libraries/architecture/coroutines)[]()
<br/>
远端数据的更新流程为:<br/><br/>
<center>
![file](https://img2018.cnblogs.com/blog/1820853/201909/1820853-20190930133422779-1614304702.jpg)
</center>
<br/>
将上述四个控件分别绑定对应的LiveData对象,增加其数据变化,就能够实现前文描述的APP动态变化效果了。 <br/>
[帮助文档](https://developer.android.google.cn/topic/libraries/architecture/livedata)
&ensp;
[源码路径](https://github.com/android/architecture-components-samples)<br/><br/>
小技巧: github 代码下载速度慢,可以克隆到码云上(gitee.com)再下载。
<br/><br/>
通过这四个控件的LiveData与UI的交互使用,你学会如何使用LiveData了吗? <br/><br/>
<center><font color='green'>欢迎关注公众号,留言讨论更多技术问题。</center>
<center>
![file](https://img2018.cnblogs.com/blog/1820853/201909/1820853-20190930133422967-2082437845.jpg)
</center>

Jetpack系列:LiveData入门级使用方法的更多相关文章

  1. iconfont 入门级使用方法

    iconfont : what? 阿里妈妈MUX倾力打造的矢量图标管理.交流平台.设计师将图标上传到Iconfont平台,用户可以自定义下载多种格式的icon,平台也可将图标转换为字体,便于前端工程师 ...

  2. Jetpack系列:应用内导航的正确使用方法

    今天小编要分享的还是Android Jetpack库的基本使用方法,本篇介绍的内容是Jetpack Navigation组件,让我们一起学习,为完成年初制定的计划而努力吧! *** 组件介绍 导航,是 ...

  3. Google C++测试框架系列:入门

    Google C++测试框架系列:入门 原始链接:V1_6_Primer 注 GTest或者Google Test: Google的C++测试框架. Test Fixtures: 这个词实在找不到对应 ...

  4. Python系列之入门篇——HDFS

    Python系列之入门篇--HDFS 简介 HDFS (Hadoop Distributed File System) Hadoop分布式文件系统,具有高容错性,适合部署在廉价的机器上.Python ...

  5. Python系列之入门篇——MYSQL

    Python系列之入门篇--MYSQL 简介 python提供了两种mysql api, 一是MySQL-python(不支持python3),二是PyMYSQL(支持python2和python3) ...

  6. 【转】C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子。

    C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子. 标签: c#objectnewlineexceptionbytestring 2010-05-17 01:10 117109人阅读 ...

  7. .NET 4 并行(多核)编程系列之一入门介绍

    .NET 4 并行(多核)编程系列之一入门介绍 本系列文章将会对.NET 4中的并行编程技术(也称之为多核编程技术)以及应用作全面的介绍. 本篇文章的议题如下:  1. 并行编程和多线程编程的区别.  ...

  8. LINQ学习系列-----1.3 扩展方法

    这篇内容继续接着昨天的Lambda表达式的源码继续下去.昨天讲了Lambda表达式,此篇讲扩展方法,这两点都是Linq带来的新特性.    一.扩展方法介绍   废话不多说,先上源码截图: 上图中Ge ...

  9. Pandas系列之入门篇

    Pandas系列之入门篇 简介 pandas 是 python用来数据清洗.分析的包,可以使用类sql的语法方便的进行数据关联.查询,属于内存计算范畴, 效率远远高于硬盘计算的数据库存储.另外pand ...

随机推荐

  1. CodeForces 804C Ice cream coloring

    Ice cream coloring 题解: 这个题目中最关键的一句话是, 把任意一种类型的冰激凌所在的所有节点拿下来之后,这些节点是一个连通图(树). 所以就不会存在多个set+起来之后是一个新的完 ...

  2. Codeforces Round #481 (Div. 3) A. Remove Duplicates

    题目地址:http://codeforces.com/contest/978/problem/A 题解:给一串长度为n的数组,然后删去相同的数字(从右往左). 方法:题目n和数组ai给的范围都很小,所 ...

  3. CF1005E1 Median on Segments (Permutations Edition) 思维

    Median on Segments (Permutations Edition) time limit per test 3 seconds memory limit per test 256 me ...

  4. react页面内嵌微信二维码 和 自定义样式 以及 微信网页共用unionId问题

    在react页面内嵌“微信二维码”,实现PC端通过微信扫码进行登录.首先去微信开放平台注册一个账号,创建一个网站应用,提交网站备案审核,获取appid和appsecret:其他开发流程根据微信文档来进 ...

  5. 前端利器躬行记(4)——webpack进阶

    webpack是一个非常强大的工具,除了前文所介绍的基础概念之外,还有各种进阶应用,例如Source Map.模块热替换.集成等,本文会对这些内容做依次讲解. 一. runtime和manifest ...

  6. webpack多页面应用打包问题-新增页面打包JS影响旧有JS资源

    webpack多页面应用打包问题:如果在项目里新增页面,pages目录中插入一个页面文件,然后打包代码,在webpack3中,新增页面文件上方文件打包出来的JS文件内容全部会改变,点击查看比对,发现问 ...

  7. Codeforces1093E_Intersection of Permutations

    题意 给定两个排列a和b,两种操作,交换b_i和b_j,询问a[l_a...r_a]和b[l_b...r_b]有多少个数相同. 分析 由于给的是排列,保证b的每个数都有a的对应,构造数组c,c[i]表 ...

  8. redis.windows.conf配置详解

    redis.windows.conf配置详解 转自:https://www.cnblogs.com/kreo/p/4423362.html # redis 配置文件示例 # 当你需要为某个配置项指定内 ...

  9. Nuget打包类库及引用

    什么是nuget 适用于任何现代开发平台的基本工具可充当一种机制,通过这种机制,开发人员可以创建.共享和使用有用的代码. 通常,此类代码捆绑到"包"中,其中包含编译的代码(如 DL ...

  10. Slickflow.NET 开源工作流引擎快速入门之三: 简单或分支流程代码编写示例

    前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从请假流程,或分支模式来快速了解引擎代码的编写. 1. 创建或分支流程图形 或分支流程是常见的 ...