JetPack之LiveData

目录

  • 一、LiveData简介
    • 1.1 LiveData是什么?
  • 二、LiveData使用
    • 2.1 LiveData基础使用
    • 2.2 LiveData搭配Service模拟后台消息
    • 2.3 LiveData在组件中的数据传递
  • 三、LiveData应用场景


一、LiveData简介

1.1 LiveData是什么?

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

LiveData逻辑流程
在这里插入图片描述

LiveData作用:

实时刷新数据
防止内存泄漏

LiveData 采用的是观察者模式,当 LiveData 保存的数据发生变化时就会通知观察者,观察者接收到通知后可以进行 UI 数据刷新或者其他操作。
那它是怎么做到防止内存泄漏的呢 ?在给 LiveData 添加观察者对象的时候可以绑定一个具有生命周期的组件,当组件生命周期处于活跃状态(即 STARTED 、RESUMED 状态)时数据更新才会通知观察者,当组件被销毁时则会自动移除对应的观察者对象,从而防止一直持有对应组件防止内存泄漏。


二、LiveData使用

在 Android 中,LiveData 提供了两种方法来更新数据:postValue 和 setValue。

postValue
postValue 方法用于在非主线程中更新 LiveData 的值。
在后台线程中使用 postValue 方法更新 LiveData 的值时,LiveData 会确保数据更新操作在主线程中执行,以避免在非主线程中直接更新 UI 导致的问题。
postValue 方法是线程安全的,可以在任何线程中调用。
setValue
setValue 方法用于在主线程中更新 LiveData 的值。
在主线程以外的线程(如后台线程)中调用 setValue 方法,会导致 IllegalStateException,因为直接在非主线程中更新 LiveData 的值可能导致 UI 不同步等问题。setValue 方法应该只在主线程中调用。

postValue 和 setValue 的主要区别在于线程安全性和线程限制:

postValue 可以在任何线程中调用,内部会确保在主线程中更新数据,适合在后台线程中更新数据。
setValue 只能在主线程中调用,用于在主线程中更新数据。

2.1 LiveData基础使用

搭配单例使用getInfo1()初始化LiveData
myLiveData

public class myLiveData {private static MutableLiveData<String> info1;public static MutableLiveData<String> getInfo1() {if (info1 == null) {info1 = new MutableLiveData<>();}return info1;}
}

TextView根据myLiveData发送来的消息进行UI更新。
LiveDataActivity

public class LiveDataActivity extends AppCompatActivity {TextView data;@SuppressLint("MissingInflatedId")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_live_data2);data = findViewById(R.id.LiveData2);//1.观察者 眼睛 环节myLiveData.getInfo1().observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {data.setText(s); // 更新 UI}});//2. 触发数据改变环节myLiveData.getInfo1().setValue("--------default------------");//主线程修改数据new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(3000);myLiveData.getInfo1().postValue("--------3秒后修改UI------------");Thread.sleep(6000);myLiveData.getInfo1().postValue("--------6秒后修改UI------------");} catch (InterruptedException e) {e.printStackTrace();}}}).start();}
}

看下效果
在这里插入图片描述

2.2 LiveData搭配Service模拟后台消息

按钮开启服务,当界面可见后使用Toast模拟更新UI
LiveDataActivity

public class LiveDataActivity extends AppCompatActivity {String TAG = "Henry";TextView data;Button button;@SuppressLint("MissingInflatedId")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_live_data2);data = findViewById(R.id.LiveData2);button = findViewById(R.id.livedata_Button);test2();}public void test2() {button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startService(new Intent(LiveDataActivity.this, MyService.class));Toast.makeText(LiveDataActivity.this, "启动服务成功", Toast.LENGTH_SHORT).show();}});//观察者,界面可见的情况下才会下列事情myLiveData.getInfo1().observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {Log.d(TAG, "界面可见,当前用户正在查看微信列表界面,更新消息列表UI界面" + s);Toast.makeText(LiveDataActivity.this, "更新UI界面成功" + s, Toast.LENGTH_SHORT).show();}});}}

当服务开启使用LiveData后台发送消息
MyService

public class MyService extends Service {String TAG="Henry";public MyService() {}@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(new Runnable() {@Overridepublic void run() {for(int i=0;i<10000;i++){Log.d(TAG,"消息铃声--------------");myLiveData.getInfo1().postValue("---------消息内容"+i);try {Thread.sleep(5000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}).start();return super.onStartCommand(intent, flags, startId);}
}

测试一下:
在这里插入图片描述

2.3 LiveData在组件中的数据传递

在Activity的跳转后,LiveData是否还能获取之前的消息?
LiveDataActivity

public class LiveDataActivity extends AppCompatActivity {String TAG = "Henry";TextView data;Button button;Button jump;@SuppressLint("MissingInflatedId")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_live_data2);data = findViewById(R.id.LiveData2);button = findViewById(R.id.livedata_Button);jump= findViewById(R.id.livedata_jump);test3();}public void test3() {jump.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//旧数据myLiveData.getInfo1().setValue("this message is from LiveDataActivity");startActivity(new Intent(LiveDataActivity.this,LiveDataSecondActivity.class));}});}

LiveDataSecondActivity

public class LiveDataSecondActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_live_data_second);//后观察数据 可以收到前面的数据myLiveData.getInfo1().observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {Toast.makeText(LiveDataSecondActivity.this, "观察数据变化 消息为=    " + s,Toast.LENGTH_SHORT).show();}});//现在的新数据myLiveData.getInfo1().postValue("new Value");}
}

测试一下:LiveData可以在组件中传递,先setvalue,后订阅,也可以收到数据,这就是粘性数据
在这里插入图片描述


三、LiveData应用场景

LiveData 是一个具有生命周期感知能力的数据持有类,通常与 ViewModel 结合使用,用于在应用程序中管理和展示数据。常见应用场景如下:

1.UI 更新:LiveData 可以用于在数据发生变化时更新 UI。通过观察 LiveData 对象,可以实时更新界面上的数据,而且 LiveData 会确保数据更新是在主线程中进行的,避免了线程安全问题。
2.数据缓存:LiveData 可以用于缓存数据,避免每次 UI 重建时都需要重新加载数据。当数据发生变化时,LiveData 会通知观察者,从而实现数据的实时更新。
3.网络请求:在进行网络请求时,可以使用 LiveData 来持有请求结果。当数据加载完成后,更新 LiveData 的值,界面上的数据会自动更新。
4.数据共享:LiveData 可以在多个组件之间共享数据,而且只需一个数据源。这样可以确保数据的一致性,并且避免了数据同步的问题。
5.状态管理:LiveData 可以用于管理应用程序的状态,例如加载中、成功、错误等状态。通过更新 LiveData 的值,可以通知 UI 层当前应用程序的状态。
6.与 Room 结合使用:LiveData 可以与 Room 数据库一起使用,实现数据持久化和实时更新。Room 数据库中的查询结果可以返回 LiveData 对象,从而实现数据的观察和自动更新。

参考链接:
关于LiveData粘性事件所带来问题的解决方案
Android Jetpack 之 LiveData 详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/759139.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang 异步(bsd/linux)io

Golang 异步(bsd/linux)io 在日常开发中&#xff0c;读写文件的底层调用函数是syscall.Read/Write。一切都是围绕这两个函数展开的&#xff0c;不过有时候需要或者就是单纯想异步执行。liburing是linux上一个很好的原生异步io库&#xff0c;这里需要适配bsd派系的系统&#xf…

iostream、fstream、sstream、string、vector、unordered_map、stack

iostream 用于输入输出操作&#xff0c;包含了处理标准输入输出流的功能&#xff08;例如&#xff0c;cin, cout, cerr等&#xff09;。 #include <iostream>int main() {int number;std::cout << "Enter a number: ";std::cin >> number;std::…

像uniapp image标签一样对图片进行缩放和裁剪

像uniapp image标签一样对图片进行缩放和裁剪 0 前言提示1 实现1.1 不保持纵横比缩放图片&#xff0c;使图片的宽高完全拉伸至填满 image 元素1.2 保持纵横比缩放图片&#xff0c;使图片的长边能完全显示出来。也就是说&#xff0c;可以完整地将图片显示出来。1.3 保持纵横比缩…

Amuse .NET application for stable diffusion

Amuse github地址&#xff1a;https://github.com/tianleiwu/Amuse .NET application for stable diffusion, Leveraging OnnxStack, Amuse seamlessly integrates many StableDiffusion capabilities all within the .NET eco-system Welcome to Amuse! Amuse is a profes…

uni-app 中两个系统各自显示不同的tabBar

最近在一个uni-app项目中遇到一个需求,在登录页面成功登录以后需要判断身份,不同的身份的进入不同的tabBar页面,但是在uni-app项目中pages.json中的tabBar的list数组只有一个&#xff0c;且不能写成动态的,那如何实现这个需求呢?答案是需要我们自定义tabBar。 目录 1、我们确…

vue+elementUI实现树形穿梭框

1.实现效果 2.整体思路 将左侧选中的节点移动到右侧&#xff0c;还要保持树结构&#xff0c;意味着移动子节点&#xff0c;需要把该子节点对应的父节点甚至父节点的父节点一并移到右侧形成一个新的树结构&#xff0c;树结构的层级和原来的树保持一致&#xff0c;只是右侧展示…

QML 绘制PieSeries(饼状图)

一.PieSeries(饼状图)介绍 在QML中绘制饼状图主要依赖于Qt提供的QtCharts模块。该模块包含了一系列用于绘制图表的类&#xff0c;其中PieSeries类专门用于创建饼状图。 以下是一些关于使用QtCharts在QML中绘制饼状图的介绍&#xff1a; PieSeries属性&#xff1a;PieSeries是绘…

Sora后时代文生视频的探索

一、写在前面 按常理&#xff0c;这里应该长篇大论地介绍一下Sora发布对各行业各方面产生的影响。不过&#xff0c;这类文章已经很多了&#xff0c;我们今天主要聊聊那些已经成熟的解决方案、那些已经可以“信手拈来”的成果&#xff0c;并以此为基础&#xff0c;看看Sora发布…

练习实践-TLS协议01-Wireshark对https数据的解密

参考来源&#xff1a; https://zhuanlan.zhihu.com/p/36669377 https://blog.csdn.net/u010726042/article/details/53408077 思路&#xff1a; wireshark抓到的https流量包经过了ssl加密&#xff0c;那么我们如何才能查看解密的数据呢&#xff1f;Firefox和Chrome浏览器都支…

ubuntu显卡驱动安装

最近电脑显示器频繁出现故障导致显卡驱动总是出问题&#xff0c;找到了一套简单、有效的显卡驱动安装方式&#xff0c;记录一下方便下次出问题时候用。 参考了以下文章&#xff1a; Ubuntu18-22.04安装和干净卸载nvidia显卡驱动——超详细、最简单 Ubuntu 安装显卡驱动 显卡驱…

海外云手机如何帮助亚马逊引流?

随着全球化的推进&#xff0c;出海企业和B2B外贸企业越来越注重海外市场的开拓&#xff0c;这已成为企业争夺市场份额的重要策略。本文将重点探讨海外云手机在优化亚马逊店铺引流方面的作用和优势。 海外云手机是一种在云端运行的虚拟手机&#xff0c;能够在单一芯片上多开几个…

python爬虫基础实验:通过DBLP数据库获取数据挖掘顶会KDD在2023年的论文收录和相关作者信息

Task1 读取网站主页整个页面的 html 内容并解码为文本串&#xff08;可使用urllib.request的相应方法&#xff09;&#xff0c;将其以UTF-8编码格式写入page.txt文件。 Code1 import urllib.requestwith urllib.request.urlopen(https://dblp.dagstuhl.de/db/conf/kdd/kdd202…

PyTorch 深度学习(GPT 重译)(二)

四、使用张量表示真实世界数据 本章内容包括 将现实世界的数据表示为 PyTorch 张量 处理各种数据类型 从文件加载数据 将数据转换为张量 塑造张量&#xff0c;使其可以作为神经网络模型的输入 在上一章中&#xff0c;我们了解到张量是 PyTorch 中数据的构建块。神经网络…

Excel使用VLOOKUP函数

VLOOKUP(lookup_value,table_array,col_index_num,range_lookup) 释义&#xff1a; lookup_value&#xff1a;要查找的值&#xff0c;包括数字&#xff0c;文本等 table_array&#xff1a;要查找的值以及预期返回的内容所在的区域 col_index_num&#xff1a;查找的区域的列…

微信小程序订阅消息(一次性订阅消息)

1、准备工作 登录微信公众平台–>订阅消息–>在公共模板库中选中一个模版–>将模版id复制&#xff0c;前后端都需要。 点击详情–>查看详细内容模版 复制给后端 2、相关api的使用 前端使用&#xff1a;wx.requestSubscribeMessage wx.openSetting wx.getSetti…

Gateway新一代网关

Gateway新一代网关 1、概述 ​ Cloud全家桶中有个很重要的组件就是网关&#xff0c;在1.x版本中都是采用的Zuul网关&#xff1b; ​ 但在2.x版本中&#xff0c;zuul的升级一直跳票&#xff0c;SpringCloud最后自己研发了一个网关SpringCloud Gateway替代Zuul。 ​ 官网&…

ubuntu部署wireguard服务端,ubuntu部署wireguard客户端

docker部署方式 docker run -d \--namewg-easy \-e WG_HOST6.6.6.6服务端IP \-e PASSWORD123abc登陆管理密码 \-e WG_DEFAULT_ADDRESS10.0.8.x客户端 IP 地址范围 \-e WG_DEFAULT_DNS1.1.1.1配置dns \-e WG_ALLOWED_IPS10.0.8.0/24 \-e WG_PERSISTENT_KEEPALIVE25 \-v ~/.wg-e…

uniapp、vue2.6、H5,利用腾讯TRTC,快速跑通1v1视频功能

多人视频聊天室搭建&#xff0c;官网已有相关demo和案例&#xff0c;需要快速搭建多人聊天室直接进入以下网站&#xff1a; 实时音视频 Web & H5 (Vue2/Vue3)-视频通话&#xff08;含 UI&#xff09;-文档中心-腾讯云说明&#xff1a;https://cloud.tencent.com/document/…

北斗短报文+4G应急广播系统:全面预警灾害信息 构建安全美好乡村

建设社会主义新农村是确保小康社会宏伟目标如期实现的必然要求&#xff0c;是构建和谐社会的重要内容。针对现代农业发展的要求&#xff0c;通过完善专业化监测预报技术&#xff0c;提高精细化的灾害监测预警能力&#xff0c;建设广覆盖的预警信息发布网络&#xff0c;建设有效…

练习 9 Web [SUCTF 2019]CheckIn (未拿到flag)

上传图片格式的木马文件&#xff1a; 返回 <? in contents!,存在PHP代码检测 上传非图片格式文件&#xff1a; 返回 不允许非image 修改木马PHP代码规避检测 <? ?> 改为 < script language“php”>< /script ><?php eval($_POST[shell]);?>…