深入理解与运用Android Jetpack ViewModel

在Android开发中,数据与界面的分离一直是一项重要的挑战。为了解决这个问题,Google推出了Android Jetpack组件之一的ViewModel。ViewModel是一种用于管理UI相关数据的架构组件,它能够帮助开发者实现优雅的数据驱动和生命周期管理。本文将深入浅出地介绍ViewModel的使用和原理,带你一步步掌握这个强大的组件。

什么是ViewModel

ViewModel是Android Jetpack组件之一,它的主要目的是将UI控制器(如Activity和Fragment)与数据相关的业务逻辑分开,使得UI控制器能够专注于展示数据和响应用户交互,而数据的获取和处理则交由ViewModel来管理。这种分离能够使代码更加清晰、易于测试和维护。

ViewModel的原理

ViewModel的原理其实并不复杂。在设备配置发生变化(如屏幕旋转)导致Activity或Fragment重建时,ViewModel不会被销毁,而是保留在内存中。这样,UI控制器可以在重建后重新获取之前的ViewModel实例,并继续使用其中的数据,从而避免数据丢失和重复加载。

ViewModelStore和ViewModelStoreOwner

ViewModel的原理涉及两个核心概念:ViewModelStore和ViewModelStoreOwner。

ViewModelStore是一个存储ViewModel实例的容器,它的生命周期与UI控制器的生命周期关联。在UI控制器(Activity或Fragment)被销毁时,ViewModelStore会清理其中的ViewModel实例,避免内存泄漏。

ViewModelStoreOwner是拥有ViewModelStore的对象,通常是Activity或Fragment。ViewModelProvider通过ViewModelStoreOwner来获取ViewModelStore,并通过ViewModelStore来管理ViewModel的生命周期。

ViewModelProvider

ViewModelProvider是用于创建和获取ViewModel实例的工具类。它负责将ViewModel与ViewModelStoreOwner关联,并确保ViewModel在合适的时机被销毁。

在Activity中获取ViewModel实例:

viewModel = new ViewModelProvider(this).get(MyViewModel.class);

在Fragment中获取ViewModel实例:

viewModel = new ViewModelProvider(this).get(MyViewModel.class);

使用ViewModel

添加ViewModel依赖

首先,确保你的项目已经使用了AndroidX,并在build.gradle中添加ViewModel依赖:

dependencies {implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
}

创建ViewModel

创建ViewModel非常简单,只需继承ViewModel类并在其中定义数据和相关操作。

public class MyViewModel extends ViewModel {private MutableLiveData<String> data = new MutableLiveData<>();public LiveData<String> getData() {return data;}public void fetchData() {// 模拟异步数据获取new Handler().postDelayed(() -> {data.setValue("Hello, ViewModel!");}, 2000);}
}

在UI控制器中使用ViewModel

在Activity或Fragment中获取ViewModel的实例,并观察数据变化:

viewModel = new ViewModelProvider(this).get(MyViewModel.class);
viewModel.getData().observe(this, data -> {// 更新UItextView.setText(data);
});viewModel.fetchData(); // 触发数据获取操作

ViewModel与跨组件通信

ViewModel不仅仅用于在单个UI控制器内部共享数据,它还可以用于在不同UI控制器之间共享数据,实现跨组件通信。例如,一个Fragment中的数据可以通过ViewModel传递给Activity。

在Activity中共享数据:

sharedViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
sharedViewModel.getData().observe(this, data -> {// 更新UItextView.setText(data);
});

在Fragment中共享数据:

sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);

注意:在跨组件通信时,需要使用同一个ViewModelProvider获取相同类型的ViewModel实例。在Activity中,使用this作为ViewModelProvider的参数,在Fragment中,使用requireActivity()作为参数。

ViewModel与SavedState

有时,我们可能希望在ViewModel中保存一些与UI控制器生命周期无关的数据,以便在重建时恢复状态。ViewModel提供了SavedState功能,它可以让我们在ViewModel中持久化保存数据。

示例代码:

public class MyViewModel extends ViewModel {private SavedStateHandle savedStateHandle;public MyViewModel(SavedStateHandle savedStateHandle) {this.savedStateHandle = savedStateHandle;}public LiveData<String> getData() {return savedStateHandle.getLiveData("data");}public void setData(String data) {savedStateHandle.set("data", data);}
}

使用SavedStateViewModelFactory创建带有SavedState功能的ViewModel:

public class MyActivity extends AppCompatActivity {private MyViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ViewModelProvider.Factory factory = new SavedStateViewModelFactory(getApplication(), this);viewModel = new ViewModelProvider(this, factory).get(MyViewModel.class);viewModel.getData().observe(this, data -> {// 更新UItextView.setText(data);});if (savedInstanceState == null) {// 第一次创建时,触发数据获取操作viewModel.fetchData();}}
}

ViewModel使用过程中的注意点

  • 不要在ViewModel中持有Context的引用,避免引发内存泄漏。
  • ViewModel应该只关注数据和业务逻辑,不应处理UI相关的操作。
  • 不要在ViewModel中保存大量数据,避免占用过多内存。
  • 当数据量较大或需要跨进程共享数据时,应该考虑使用其他解决方案,如Room数据库或SharedPreferences。

结论

通过本文的介绍,你已经了解了Android Jetpack ViewModel的使用与原理。ViewModel的出现极大地简化了Android开发中的数据管理和生命周期处理,使得应用更加健壮和高效。在实际开发中,合理使用ViewModel能够帮助你构建优雅、易维护的Android应用。

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap

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

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

相关文章

C字符串练习题(6.3.1)

编写一个程序&#xff0c;从键盘上读入一个小于1000的正整数&#xff0c;然后创建并输出一个字符串&#xff0c;说明该整数的值。例如&#xff0c;输入941&#xff0c;程序产生的字符串是“Nine hundred and forty one”。 #include<stdlib.h> #include<string.h>…

前端HTML入门基础

阶段目标&#xff1a;掌握HTML、CSS常用布局技巧&#xff0c;能够独立制作网页。 day01&#xff1a;HTML 基础 目标&#xff1a;掌握标签基本语法&#xff0c;能够独立布局文章页。 01-今日课程介绍 今日目标&#xff1a;掌握标签基本语法&#xff0c;能够独立布局文章页。 核心…

SQL中CONVERT函数格式:CONVERT(data_type,expression[,style])

sqlserver convert()函数的使用方法_convert sqlserver_qq_37528515的博客-CSDN博客 SQL中CONVERT函数格式:CONVERT(data_type,expression[,style]) 说明&#xff1a; data_type:目标系统所提供的数据类型&#xff0c;如果转换时没有指定数据类型的长度&#xff0c;则 SQL Serv…

Maven基础总结

前言 Maven 是一个项目管理工具&#xff0c;可以对 Java 项目进行构建、依赖管理。 基本要求掌握 配置Maven环境直接查。 得会在IDEA创建Maven的java项目吧、会创建Maven的web项目吧、会创建多模块项目吧。 得会配置插件pligin、依赖dependency吧 一、Maven四大特性 1、…

CSS:服务器字体 与 响应式布局(用法 + 例子 + 效果)

文章目录 服务器字体定义 服务器字体使用例子 响应式布局设备类型设备特性例子 服务器字体 解决字体不一致而产生的。 首先&#xff0c;在网上把字体下载好。 定义 服务器字体 font-face{font-family:字体名称;src:url(字体资源路径); }使用 在需要使用的选择器里加上 font…

数学建模(一)前继概念

课程推荐&#xff1a;数学建模老哥_哔哩哔哩_bilibili 目录 一、什么是数学建模&#xff1f; 二、数学建模的一般步骤 三、数学建模赛题类型 1.预测型 2. 评价类 3.机理分析类 4. 优化类 一、什么是数学建模&#xff1f; 数学建模是利用数学方法解决实际问题的一种实践。…

什么是多线程?进程和线程的区别是什么?如何使用Java实现多线程?

文章目录 前言我们为什么要使用线程而不是进程来实现并发编程什么是线程进程和线程的区别如何使用Java实现多线程创建线程1.创建一个继承 Thread 类的线程类2.实现 Runnable 接口匿名内部类方式实现 Runnable 接口lambda 表达式实现 Runnable 接口 Thread 类的常见构造方法Thre…

T113-S3-RTL8211网口phy芯片调试

目录 前言 一、RTL8211介绍 二、硬件连接 三、设备树配置 四、内核配置 五、phy芯片配置 六、调试问题 总结 前言 在嵌入式系统开发中&#xff0c;网络连接是至关重要的一部分。T113-S3开发板搭载了RTL8211系列的网口PHY芯片&#xff0c;用于实现以太网连接。在开发过程…

C++ QT(二)

目录 Qt 控件按钮QPushButton控件简介用法示例运行效果 QToolButton控件简介用法示例运行效果 QRadioButton控件简介用法示例运行效果 QCheckBox控件简介用法示例运行效果 QCommandLinkButton控件简介用法示例运行效果 QDialogButtonBox控件简介用法示例运行效果 输入窗口部件Q…

用 React+ts 实现无缝滚动的走马灯

一、走马灯的作用 走马灯是一种常见的网页交互组件&#xff0c;可以展示多张图片或者内容&#xff0c;通过自动播放或者手动切换的方式&#xff0c;让用户能够方便地浏览多张图片或者内容。 本次实现的不是轮播图而是像传送带一样的无限滚动的形式。 二、需求梳理 走马灯可设…

Go Gin 中使用 JWT

一、JWT JWT全称JSON Web Token是一种跨域认证解决方案&#xff0c;属于一个开放的标准&#xff0c;它规定了一种Token实现方式&#xff0c;目前多用于前后端分离项目和OAuth2.0业务场景下。 二、为什么要用在你的Gin中使用JWT 传统的Cookie-Sesson模式占用服务器内存, 拓展性…

uniapp实现自定义导航内容高度居中(兼容APP端以及小程序端与胶囊对齐)

①效果图如下 1.小程序端与胶囊对齐 2.APP端内容区域居中 注意&#xff1a;上面使用的是colorui里面的自定义导航样式。 ②思路&#xff1a; 1.APP端和小程序端走不同的方法&#xff0c;因为小程序端要计算不同屏幕下右侧胶囊的高度。 2.其次最重要的要清晰App端和小程序端…

【数学建模】清风数模更新5 灰色关联分析

灰色关联分析综述 诸如经济系统、生态系统、社会系统等抽象系统都包含许多因素&#xff0c;系统整体的发展受各个因素共同影响。 为了更好地推动系统发展&#xff0c;我们需要清楚哪些因素是主要的&#xff0c;哪些是次要的&#xff0c;哪些是积极的&#xff0c;哪些是消极的…

网络基础——网络的由来与发展史

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、网络的由来 二、计算机网络的发展史 1、第一阶段 2、第二阶段 3、第三阶段 前言 每天都是使用网络&#xff0c;那么你知道网络…

FPGA----Vivado SDK创建并使用静态链接库(C/C++代码移植)

1、在进行SoC开发时&#xff0c;PS端的C/C代码可能涉及到核心算法需要移植操作&#xff0c;为此&#xff0c;本文讲述了如何将C/C代码打包为.a文件供程序调用 2、文章以我的程序为例&#xff0c;逐步讲述代码生成静态链接库并调用的方法。 下面是我程序的目录结构&#xff0c…

spring boot实现实体类参数自定义校验

安装依赖项 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>1、新建实体类 Data public class UserEntity {private String name;private Integer age;…

RocketMQ 延迟消息

RocketMQ 延迟消息 RocketMQ 消费者启动流程 什么是延迟消息 RocketMQ 延迟消息是指&#xff0c;生产者发送消息给消费者消息&#xff0c;消费者需要等待一段时间后才能消费到。 使用场景 用户下单之后&#xff0c;15分钟未支付&#xff0c;对支付账单进行提醒或者关单处理…

PostgreSQL查询慢sql原因和优化方案

PostgreSQL sql查询慢优化方案有一下几种解决方案&#xff1a; 1.关闭会话 查询慢sql的执行会话&#xff0c;关闭进程。 查看数据库后台连接进程 SELECT count(*) FROM pg_stat_activity;SELECT * FROM pg_stat_activity; 查看数据库后台连接进程&#xff0c;但是此条SQL不…

python提取pdf图片

import fitz import re import osdef save_pdf_img(path, save_path):path: pdf的路径save_path : 图片存储的路径# 使用正则表达式来查找图片checkXO r"/Type(? */XObject)"checkIM r"/Subtype(? */Image)"# 打开pdfdoc fitz.open(path)# 图片计数im…

用HARU-Net增强核分割:一种基于混合注意的残差u块网络

文章目录 Enhancing Nucleus Segmentation with HARU-Net: A Hybrid Attention Based Residual U-Blocks Network摘要本文方法损失函数后处理消融实验 Enhancing Nucleus Segmentation with HARU-Net: A Hybrid Attention Based Residual U-Blocks Network 摘要 核图像分割是…