ViewModel 原理

# ViewModel 原理

在现代Android应用开发中,ViewModel是架构组件库的一个关键部分,它在提高应用的稳定性和性能方面发挥着重要作用。在这篇文章中,我们将深入探讨ViewModel的工作原理和最佳实践。

ViewModel简介

ViewModel是Android Jetpack架构组件的一部分,它的主要目的是管理和存储与UI相关的数据。ViewModel的设计初衷是使数据能够在配置更改(如屏幕旋转)后继续存在。

工作原理

数据持久性

  • 当设备配置更改导致Activity重建时,ViewModel可以保留数据。它是通过系统保存的实例状态来实现的,从而使数据在Activity重新创建时依然可用。

生命周期意识

  • ViewModel与Activity或Fragment的生命周期紧密相连。它在Activity或Fragment的整个生命周期内都是活跃的,并在它们被完全销毁时清理。

使用ViewModel的优势

  • 数据管理:ViewModel使得管理UI相关的数据更加简单和高效。
  • 减少内存泄漏:由于ViewModel与视图的生命周期是分离的,因此减少了因为持有Activity或Fragment引用而导致的内存泄漏的风险。
  • 更好的数据持久化:ViewModel可以在配置更改时保留重要数据,避免了不必要的数据库或网络请求。

实现ViewModel

创建ViewModel类

  • ViewModel的创建需要继承ViewModel类。
  • 可以在ViewModel内部实现数据的加载和处理逻辑。

与Activity或Fragment关联

  • ViewModel通过ViewModelProvider与Activity或Fragment绑定。
  • 这样可以确保ViewModel的生命周期与Activity或Fragment的生命周期同步。

处理配置更改

  • 在配置更改(如屏幕旋转)时,ViewModel帮助保存重要的UI数据。
  • 当Activity或Fragment重新创建时,可以从ViewModel中恢复数据。

最佳实践

  • 避免在ViewModel中引用视图:ViewModel不应持有对Activity、Fragment或View的引用。
  • 使用LiveData:LiveData可以用来观察数据的变化,并在数据变化时更新UI。
  • 分离关注点:ViewModel应该专注于数据处理,而UI逻辑应该留在Activity或Fragment中。

ViewModel的创建方式

1. 使用ViewModelProvider

这是创建ViewModel的最常见方式。ViewModelProvider会与Activity或Fragment的生命周期关联,确保在配置更改时ViewModel不会被重新创建。

import androidx.lifecycle.ViewModelProvider
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundleclass MainActivity : AppCompatActivity() {private lateinit var viewModel: MyViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)viewModel = ViewModelProvider(this).get(MyViewModel::class.java)}
}

在这个例子中,MyViewModel 是通过ViewModelProvider创建的,并与MainActivity的生命周期关联。

2. 使用ViewModel的工厂方法

当需要向ViewModel传递参数时,可以使用ViewModel的工厂方法来创建ViewModel。

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundleclass MyViewModel(val myParam: String) : ViewModel() {// ViewModel的逻辑
}class MyViewModelFactory(private val myParam: String) : ViewModelProvider.Factory {override fun <T : ViewModel?> create(modelClass: Class<T>): T {if (modelClass.isAssignableFrom(MyViewModel::class.java)) {return MyViewModel(myParam) as T}throw IllegalArgumentException("Unknown ViewModel class")}
}class MainActivity : AppCompatActivity() {private lateinit var viewModel: MyViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val factory = MyViewModelFactory("Hello")viewModel = ViewModelProvider(this, factory).get(MyViewModel::class.java)}
}

在这个例子中,MyViewModel 需要一个字符串参数。因此,创建了一个MyViewModelFactory
来传递这个参数,并使用这个工厂来创建MyViewModel的实例。


ViewModel 相关面试题及回答

面试题1: ViewModel是什么,它是如何工作的?

  • 回答:
    ViewModel是一个架构组件,它的主要职责是管理界面控制器(如Activity和Fragment)的数据。它帮助保存数据,以便在配置更改(如屏幕旋转)时数据不会丢失。ViewModel的实例与特定的Activity或Fragment的生命周期绑定,但比单个Activity或Fragment的实例生命周期更长,因此能够在界面控制器重建时保持数据状态。

面试题2: 为什么在ViewModel中持有Activity的引用是一个不好的实践?

  • 回答:
    在ViewModel中持有Activity的引用会导致内存泄露,因为ViewModel的生命周期比它所关联的Activity长。如果ViewModel持有Activity的引用,即使Activity需要被销毁以释放资源,由于ViewModel的存在,它无法被垃圾回收器回收,从而导致内存泄漏。

面试题3: LiveData是什么,它如何与ViewModel配合使用?

  • 回答:
    LiveData是一个可观察的数据存储器类,特别是用于保存可观察数据,并且能在数据改变时通知视图。它与ViewModel配合使用,因为LiveData遵循观察者模式,这使得当数据改变时,UI可以立即更新。LiveData也是生命周期感知的,这意味着它只会在Activity或Fragment处于活跃状态时更新UI,从而避免内存泄漏。

面试题4: 如何在ViewModel中处理耗时任务?

  • 回答:
    在ViewModel中处理耗时任务(如网络请求)时,应该使用后台线程来避免阻塞UI线程。可以利用协程或RxJava等异步处理框架来实现。这些任务应该与ViewModel的生命周期关联,以确保在ViewModel被销毁时,相关的异步任务也会相应地被取消或清理,以避免内存泄露。

面试题5: 解释ViewModel的onCleared()方法。

  • 回答: onCleared()
    方法在ViewModel即将被销毁时调用,这通常发生在与其关联的Activity或Fragment被永久销毁时(不是由于配置更改)。这个方法是清理资源的理想位置,比如取消所有进行中的异步任务、移除监听器或者释放对外部资源的引用。

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

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

相关文章

ubuntu安裝Avahi发现服务工具

一、简介 解决设置固定ip后无法连接外网的问题&#xff0c;目前采用动态获取ip&#xff0c;可以不用设置设备的固定IP&#xff0c;直接可以通过域名来访问设备&#xff0c;类似树莓派的连接调试 二、安装 本文使用的是ubuntu23.10.1上安装 1.安装工具 sudo apt install av…

2.模拟问题——4.日期问题

日期问题难度并不大&#xff0c;但是代码量非常大&#xff0c;需要较高的熟练度&#xff0c;因此需要着重练习&#xff0c;主要涉及数组和循环两个方面的知识点&#xff0c;需要熟练的测试代码。 两个经典题型 闰年 闰年满足以下两个条件的任意一个 能够被400整除不能够被1…

【Acwing】差分矩阵

图1&#xff1a;a和b数组映射表 由于a是b的前缀和数组&#xff0c;因此改变b[ x1][ y1]之后&#xff0c;受到影响的a中元素如右半图所示 图2&#xff1a;求b数组的前缀和 #include<bits/stdc.h> using namespace std;int n,m,q; int a[1010][1010]; int b[1010][1010]…

work 3/1

1>机械臂 #include <head.h> #define SER_POTR 8899 #define SER_IP "192.168.125.223" int main(int argc, const char *argv[]) {//创建套接字int cfdsocket(AF_INET,SOCK_STREAM,0);if(cfd-1){perror("");return -1;}//链接struct sockaddr_i…

一文搞懂浏览器缓存机制

文章目录 概述强制缓存协商缓存总结参考文章 概述 浏览器的缓存机制也就是我们说的HTTP缓存机制&#xff0c;其机制是根据HTTP报文的缓存标识进行的 浏览器第一次向服务器发送HTTP请求, 浏览器拿到请求结果后&#xff0c;会根据响应报文的缓存标识&#xff0c;决定是否进行缓存…

机器学习:数据处理基操

在处理完数据之后&#xff0c;选择好模型&#xff0c;就可以用训练集训练模型&#xff0c;用测试集输入模型 然后输出需要预测的结果啦&#xff5e; 一、模块导入 import numpy as np import pandas as pd #读入数据 二、pandas数据 一、dataframe基础 一、dataframe的创建…

【代码】Android|判断asserts下的文件存在与否,以及普通文件存在与否

作者版本&#xff1a;Android 11及以上 主要是发现网上没有完整的、能跑的代码&#xff0c;不知道怎么回事&#xff0c;GPT给我重写的。我只能保证这个代码尊嘟能跑&#xff0c;不像其他的缺胳膊少腿的。 asserts 贴一下结果&#xff1a; boolean isAssertFileExists(String …

kafka消费者接收不到消息

背景&#xff1a; 对kafka消息进行监听&#xff0c;生产者发了消息&#xff0c;但是消费端没有接到消息&#xff0c;监听代码 消费端&#xff0c;kafka配置 spring.kafka.bootstrap-serverskafka.cestc.dmp:9591 spring.kafka.properties.sasl.jaas.configorg.apache.kafka.…

29.HarmonyOS App(JAVA)通知

普通通知: 通知渠道,弹出消息后&#xff0c;自动消失 长文本通知 //多行文本通知 //图片通知 //社交通知 //媒体通知--经测试&#xff0c;图片无法显示&#xff0c;文字不显示 场景介绍 HarmonyOS提供了通知功能&#xff0c;即在一个应用的UI界面之外显示的消息&#xff0c;主…

C++之结构体以及通讯录管理系统

1&#xff0c;结构体基本概念 结构体属于自定义的数据概念&#xff0c;允许用户存储不同的数据类型 2&#xff0c;结构体的定义和使用 语法&#xff1a;struct 结构体名{ 结构体成员列表}&#xff1b; 通过结构体创建变量的方式有三种&#xff1a; 1&#xff0c;struct …

设计模式学习笔记 - 设计原则 - 8.迪米特法则(LOD)

前言 迪米特法则&#xff0c;是一个非常实用的原则。利用这个原则&#xff0c;可以帮我们实现代码的 “高内聚、松耦合”。 围绕下面几个问题&#xff0c;来学习迪米特原则。 什么是 “高内聚、松耦合”&#xff1f;如何利用迪米特法则来实现 高内聚、松耦合&#xff1f;哪些…

技术实践|百度安全「大模型内容安全」高级攻击风险评测

1、引子 2023年10月16日&#xff0c;OWASP发布了《OWASP Top 10 for LLM Applications》&#xff0c;这对于新兴的大语言模型安全领域&#xff0c;可谓一份纲领性的重要报告。 OWASP是开放式Web应用程序安全项目&#xff08;Open Web Application Security Project&#xff0…

【Linux网络命令系列】ping curl telnet三剑客

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【C++】vector的使用和模拟实现(超级详解!!!!)

文章目录 前言1.vector的介绍及使用1.1 vector的介绍1.2 vector的使用1.2.1 vector的定义1.2.2 vector iterator 的使用1.2.3 vector 空间增长问题1.2.3 vector 增删查改1.2.4 vector 迭代器失效问题。&#xff08;重点!!!!!!&#xff09;1.2.5 vector 在OJ中有关的练习题 2.ve…

C++入门和基础

目录 文章目录 前言 一、C关键字 二、命名空间 2.1 命名空间的定义 2.2 命名空间的使用 2.3 标准命名空间 三、C输入&输出 四、缺省参数 4.1 缺省参数的概念 4.2 缺省参数的分类 五、函数重载 5.1 函数重载的简介 5.2 函数重载的分类 六、引用 6.1 引用的…

搭建个人IC_EDA服务器(物理机)一:安装Centos7

1.准备 大于8G的U盘&#xff1b;待装的电脑&#xff0c;我使用淘汰的在大学时候使用的笔记本&#xff1b;U盘启动器制作工具&#xff1a;UltralSo&#xff1b;官网下载的在没有付费的情况下&#xff0c;即使试用期&#xff0c;安装的时候会有莫名的问题&#xff0c;建议使用这…

【接口测试】常见HTTP面试题

目录 HTTP GET 和 POST 的区别 GET 和 POST 方法都是安全和幂等的吗 接口幂等实现方式 说说 post 请求的几种参数格式是什么样的&#xff1f; HTTP特性 HTTP&#xff08;1.1&#xff09; 的优点有哪些&#xff1f; HTTP&#xff08;1.1&#xff09; 的缺点有哪些&#x…

Puzzles

题目链接&#xff1a;Submit - Codeforces​​​​​​ 解题思路&#xff1a; 题目大概意思就是在一个数组里找n个数里的最大值减最小值的最小值&#xff0c;先排序&#xff0c;然后将第i n - 1项减去第i项与最小值作比较&#xff0c;输出最小值即可&#xff0c;注意循环结束…

YOLOv应用开发与实现

一、背景与简介 YOLO&#xff08;You Only Look Once&#xff09;是一种流行的实时目标检测系统&#xff0c;其核心思想是将目标检测视为回归问题&#xff0c;从而可以在单个网络中进行端到端的训练。YOLOv作为该系列的最新版本&#xff0c;带来了更高的检测精度和更快的处理速…

【框架】MyBatis 框架重点解析

MyBatis 框架重点解析 1. MyBatis 执行流程 会话工厂生产的 SqlSession 对象提供了对数据库执行SQL命令所需的所有方法&#xff0c;包括但不限于以下功能&#xff1a; 数据库操作&#xff1a;SqlSession可以执行查询&#xff08;select&#xff09;、插入&#xff08;insert&a…