初探Jetpack(三) -- LiveData

2024-06-07 20:08
文章标签 初探 jetpack livedata

本文主要是介绍初探Jetpack(三) -- LiveData,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

初探Jetpack(一) – ViewModel
初探Jetpack(二) – Lifecycles

LiveData 是 Jetpack 提供的一种响应式变成组件,它可以包含任何类型的数据,并在数据发现变化的时候,通知观察者。

LiveData 具有生命周期的感知能力,指它能感觉 activity,fragment ,service 的生命周期,且只有这些组件处于活跃生命周期状态时,LiveData 感觉到数据变化,才会发出通知。

什么意思呢?即如果 activity ,fragment 等观察者处于生命周期的 STARTED, ONRESUMED状态,则 LiveData 会认为该观察者处于活跃状态,LiveData 就会将最近的通知给活跃的观察者,而非活跃状态的观察者则收不到通知。

所以,当我们把 LiveData 和 有 LifecycleOwner 接口对象结合,当 Lifecycle 的对象状态为 DESTROYED 的时候,便可移除此观察者。 这对于 Activity 和 Fragment 特别有用,因为它们可以放心地观察 LiveData 对象而不必担心泄露(当 Activity 和 Fragment 的生命周期被销毁时,系统会立即退订它们)。

即我们不用手动去处理生命周期,它会自动管理这些操作。

一、基本使用

创建 LiveData 实例以存储某种类型的数据。这通常在 ViewModel 类中完成。
在第一张章,我们学习了 ViewModel 的计时器功能 初探Jetpack(一) – ViewModel,这里再使用 LiveData 对它进行扩展:

class DataViewModel() :ViewModel() {private val _counter = MutableLiveData<Int>()val counter : LiveData<Int> get() = _counter;init {_counter.value = 0;}fun plusOne(){val size = _counter.value ?: 0;_counter.value = size+1;}
}

从上面看到,我们申明了一个 MutableLiveData 对象,并指定泛型为 Int,表示它的数据为整型。

MutableLiveData 是一种可变的 LiveData,有三个方法,分别是 getValue(),setValue()和 postValue()。

  • getValue() : 用于获取 LiveData 的数据
  • setValue() : 给 LiveData 设置数据,只能在主线程
  • postValue(): 可以在非主线程中给LiveData 设置数据
// 这里用了 getValue 和 setValue 的语法糖val size = _counter.value ?: 0;_counter.value = size+1;

为了不让外面调用 MutableLiveData,把它设置成 private,且公布出去的 counter 是 MutableLiveData 的 get() 属性方法的返回值,这样 _counter 变量就对外面不可见了。

后面我们在activity 中,这样写:

        val viewModel = ViewModelProvider(this).get(DataViewModel::class.java)plusOne.setOnClickListener{//点击增加viewModel.plusOne()}//添加数据观察者val textObserver = Observer<Int> { count ->infoText.text = count.toString()}viewModel.counter.observe(this,textObserver)

注意看到,使用了 MutableLiveData 的observe方法,它接受两个参数,第一个参数为 LifecycleOwner,直接传递 this 即可,第二是是 observe 接口,当数据发生变化时,就会毁掉这里的接口。我们把数据更新到 textview 即可,效果如下:
在这里插入图片描述

第一行代码 第三版
官网 LifeData

二、 map 和 switchMap

LiveData 为了能够应对各种不同的需求场景,提供了 map 和 switchMap 两种转换方法。

2.1 map

先看 map,这个方法的作用是将实际包含 LiveData 的数据和仅用于观察数据的 LiveData 进行转换。什么意思呢?比如我新建了一个类,User:

data class User (var firstName:String,var lastName:String,var age:Int)

然后新建一个 LiveData 来包含 User 数据:

class UserViewModel : ViewModel() {private val userViewModel = MutableLiveData<User>()}

这样看,跟上面好像没啥区别,但是 activity 中,只想显示 name,不要 age,怎么办呢?

这个时候,就可以使用 map(),它可以将 User 类型的 LiveData 自由地转型成任意其他类型的 LiveData ,如下:

class UserViewModel : ViewModel() {private val userLiveData = MutableLiveData<User>()val userName:LiveData<String> = Transformations.map(userLiveData){user -> "${user.firstName} ${user.lastName}"}fun getUserName(user: User){userLiveData.value = user;}
}

可以看到,我们使用了 Transformations.map() 方法来进行 LiveData 的类型转换,它接受两个参数,第一个 LiveData,第二个就是当 userLiveData 数据发生变化时,需要转换的逻辑,这里直接拿到它的 firstName 和 lastName。
ok,调用我们这样调用:

        val viewModel = ViewModelProvider(this).get(UserViewModel::class.java)plusOne.setOnClickListener{viewModel.getUserName(User("zhang","san",2))}//添加数据观察者viewModel.userName.observe(this, Observer { string ->infoText.text = string})

在click的时候,调用 getUserName,让数据发生变化,这里的 Observer 只需要知道它的string 即可:
在这里插入图片描述

2.2 switchMap

如果 ViewModel 中的某个 LiveData 对象是调用另外的方法获取的,则可以借助 switchMap 方法,将这个 LiveData 转换成可观察的 LiveData 对象。

什么意思呢?比如,上面的例子中,LiveData 都是在 ViewModel 中创建,但是不可能是这种理想情况,如果在外部创建呢,新建一个单利类,让它返回 livedata:

object Repository {fun getUser(name:String):LiveData<User>{val liveData = MutableLiveData<User>()liveData.value = User(name,name,0)return liveData;}
}

这里其实模仿的是,根据name,拿到一个数据库的 User 数据,这里直接新建一个 User 即可。

然后,修改一下 UserViewModel:

class UserViewModel : ViewModel() {fun getUser(name:String) : LiveData<User>{return Repository.getUser(name)}
}

获取了 LiveData 对象,那接下来呢?如何观察数据?如下写法?:

     viewModel.getUser("test").observe(this, Observer { user ->})

这肯定是不行的!!!每次 getUser 返回都是一个新的 liveData,而上述写法会一直观察老的 LiveData 实例,根本无法观察数据的变化。

这个时候,就可以使用 switchMap 了,如下修改:

class UserViewModel : ViewModel() {private val userLiveData = MutableLiveData<String>()val user : LiveData<User> = Transformations.switchMap(userLiveData){name -> Repository.getUser(name)}fun  getUser(name: String){userLiveData.value = name;}
}

可以看到,我们定义了一个 string 类型的 MutableLiveData对象,用来观察 name 的变化,然后调用 Transformations 的 switchMap 方法。它接收两个参数,第一个为LiveData ,传入userLiveData ,第二个参数时一个转换函数,注意!这个转换函数必须返回一个 LiveData 对象,这里返回时通过 Repository 返回的一个新的 LiveData 数据。

这个每次 userLiveData.value 的值发生变化,就会调用 switchMap 的转换函数啦。

在activity 中这样调用:

        val viewModel = ViewModelProvider(this).get(UserViewModel::class.java)plusOne.setOnClickListener{val name = (0..100).random().toString()viewModel.getUser(name)}viewModel.user.observe(this, Observer { user ->infoText.text = user.firstName})

效果如下,每次点,都有不同的数字
在这里插入图片描述

这篇关于初探Jetpack(三) -- LiveData的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1040169

相关文章

Java注解初探

什么是注解 注解(Annotation)是从JDK5开始引入的一个概念,其实就是代码里的一种特殊标记。这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。有了注解,就可以减少配置文件,现在越来越多的框架已经大量使用注解,而减少了XML配置文件的使用,尤其是Spring,已经将注解玩到了极致。 注解与XML配置各有

IOS Core Data框架初探

在IOS系统中已经集成了关系型数据库SqLite3数据库,但是由于在OC中直接操作C语言风格的SqLite3相对繁琐,因此Apple贴心的提供了一个ORM(Object Relational Mapping对象关系映射)框架——Core Data让我们在程序中以面向对象的方式,操作数据库。Core Data框架提供的功能相当强大,属于入门容易精通难的东西,值得我们用心专研。现在,就先记录一下我对该

Scala界面Panel、Layout初探

示例代码: package com.dt.scala.guiimport scala.swing.SimpleSwingApplicationimport scala.swing.MainFrameimport scala.swing.Buttonimport scala.swing.Labelimport scala.swing.Orientationimport scal

Java使用Redis初探

Redis的相关概念不做介绍了,大家也可以先了解下Memcached,然后比较下二者的区别,就会有个整体的印象。      服务器端通常选择Linux , Redis对于linux是官方支持的,使用资料很多,需要下载相关服务器端程序  ,然后解压安装。因为能力和条件有限,我只简单介绍下windows上如何安装和使用,有兴趣的可以娱乐一下。       服务器端程序下载地址:htt

Android JetPack ViewModel 源码解析

是什么? ViewModel 用来存储页面相关的数据,当页面销毁的时候,存储数据也会清楚。但是当页面发生旋转的时候,并不会清楚数据。 怎么用? UserViewModel userViewModel = new ViewModelProvider(this).get(UserViewModel.class); UserViewModel 是自己写的ViewModel,就可以

Android JetPack Lifecycle源码解析

是什么? JetPack Lifecycle是一个页面(Activity/Fragment)生命周期的组件,当你想监听生命周期,那么就可以使用这个组件。 怎么用? 第一种: getLifecycle().addObserver(new LifecycleObserver() {@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)publi

SQL查询优化器初探

项目中期,特意借了一本SQL优化的书,现将优化器的知识点总结如下: 查询优化器是关系型数据库管理系统的核心之一,决定对特定的查询使用哪些索引、哪些关联算法,从而使其高效运行。查询优化器是SQL Server针对用户的请求进行内部优化,生成执行计划并传输给存储引擎来操作数据,最终返回结果给用户的组件。 查询过程 T-SQL->语法分析->绑定->查询优化->执行查询->返回结果 (1)分析和

初探swift语言的学习笔记四-2(对上一节有些遗留进行处理)

作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/30314359 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号fengsh998来支持我,谢谢! 在上一节中有些问题还没有弄清,在这里自己写了一下,做了一下验证,并希望能给读者有所帮助。

初探swift语言的学习笔记四(类对象,函数)

作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/29606137 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号fengsh998来支持我,谢谢! swift扩展了很多功能和属性,有些也比较奇P。只有慢慢学习,通过经验慢慢总结了。 下面将

初探swift语言的学习笔记三(闭包-匿名函数)

作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/29353019 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号fengsh998来支持我,谢谢! 很多高级语言都支持匿名函数操作,在OC中的block也为大家所熟悉,然面在swift里好像是被