Jetpack架构组件_ViewModel组件_1.简介和示例

2024-08-28 15:04

本文主要是介绍Jetpack架构组件_ViewModel组件_1.简介和示例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.简介

       ViewModel是我们MVVM中的VM层,ViewModel类似于MVP中的P层,它是我们View层和Model层之间的一个桥梁。

1.1 和MVP的P层的主要区别是:

(1)ViewModel是与我们Android系统挂钩的,是官方的一个类,MV之间的一个桥梁。

(2)ViewModel还保持数据。

1.2 Android为什么要引入ViewModel? 

(1)分层,便于测试和维护;

(2)ViewModel解决了横竖切换时数据丢失的问题。ViewModel生命周期比较长一些,不受横竖屏切换Activity生命周期的影响。

(3)避免因疏忽而导致的内存泄露。onCleared里,写一些释放资源的代码。

1.3 Viewmodel生命周期

         Viewmodel生命周期可以参考官网地址:

ViewModel 概览  |  Android Developers

        图 1 说明了 activity 经历屏幕旋转而后结束时所处的各种生命周期状态。该图还在关联的 activity 生命周期的旁边显示了 ViewModel 的生命周期。此图表说明了 activity 的各种状态。这些基本状态同样适用于 fragment 的生命周期。

图1 ViewModel的生命周期

        通常在系统首次调用 activity 对象的 onCreate() 方法时请求 ViewModel。系统可能会在 activity 的整个生命周期内多次调用 onCreate(),如在旋转设备屏幕时。ViewModel 存在的时间范围是从首次请求 ViewModel 直到 activity 完成并销毁。

 2.代码示例

 2.1新建工程

        选Empty Views Activity。 

项目名:ViewModelDemo ,语言:Java。

 2.2  Activity定义变量

        在activity中定义变量,每次旋转屏幕后会丢失。

        MainActivity.java代码:

package com.gaoting.viewmodeldemo;import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {int score;TextView tvScore;Button btAddScore;String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tvScore = this.findViewById(R.id.tvScore);btAddScore = this.findViewById(R.id.btAddScore);btAddScore.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {score++;tvScore.setText(String.valueOf(score));}});Log.i(TAG,"onCreate");}@Overrideprotected void onDestroy() {Log.i(TAG,"onDestroy");super.onDestroy();}
}

        activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tvScore"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="成绩:0"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:layout_marginTop="30dp"app:layout_constraintTop_toBottomOf="@+id/tvScore"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"android:text="点我+1"android:id="@+id/btAddScore"android:layout_width="wrap_content"android:layout_height="wrap_content"tools:ignore="MissingConstraints"/></androidx.constraintlayout.widget.ConstraintLayout>

        运行效果:

        点击button,成绩增加到10,然后旋转屏幕发现成绩变成0了。

 2.3变量放在Viewmodel中

         新建MyViewModel类。

         MainActivity.java代码

package com.gaoting.viewmodeldemo;import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;public class MainActivity extends AppCompatActivity {TextView tvScore;Button btAddScore;String TAG = "MainActivity";MyViewModel myViewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ViewModelProvider viewModelProvider = new ViewModelProvider(this,new ViewModelProvider.NewInstanceFactory());myViewModel = viewModelProvider.get(MyViewModel.class);tvScore = this.findViewById(R.id.tvScore);tvScore.setText(String.valueOf(myViewModel.getScore()));btAddScore = this.findViewById(R.id.btAddScore);Log.i(TAG,"score init:"+tvScore.getText() +"vm:"+ myViewModel.getScore());btAddScore.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {myViewModel.addScore();tvScore.setText(String.valueOf(myViewModel.getScore()));}});Log.i(TAG,"onCreate");}@Overrideprotected void onDestroy() {Log.i(TAG,"onDestroy");super.onDestroy();}
}

         MyViewModel.java代码:

package com.gaoting.viewmodeldemo;import android.util.Log;import androidx.lifecycle.ViewModel;public class MyViewModel extends ViewModel {int score;public static final String TAG = "MyViewModel";public int getScore() {return score;}public void addScore(){score++;}@Overrideprotected void onCleared() {Log.i(TAG,"在这儿添加释放资源的代码");super.onCleared();}
}

 运行效果:

        如下图所示,可以看到旋转不会丢失数据。

这篇关于Jetpack架构组件_ViewModel组件_1.简介和示例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

Qt QCustomPlot库简介(最新推荐)

《QtQCustomPlot库简介(最新推荐)》QCustomPlot是一款基于Qt的高性能C++绘图库,专为二维数据可视化设计,它具有轻量级、实时处理百万级数据和多图层支持等特点,适用于科学计算、... 目录核心特性概览核心组件解析1.绘图核心 (QCustomPlot类)2.数据容器 (QCPDataC

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

mysql中的服务器架构详解

《mysql中的服务器架构详解》:本文主要介绍mysql中的服务器架构,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、mysql服务器架构解释3、总结1、背景简单理解一下mysqphpl的服务器架构。2、mysjsql服务器架构解释mysql的架

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

C++ 检测文件大小和文件传输的方法示例详解

《C++检测文件大小和文件传输的方法示例详解》文章介绍了在C/C++中获取文件大小的三种方法,推荐使用stat()函数,并详细说明了如何设计一次性发送压缩包的结构体及传输流程,包含CRC校验和自动解... 目录检测文件的大小✅ 方法一:使用 stat() 函数(推荐)✅ 用法示例:✅ 方法二:使用 fsee

mysql查询使用_rowid虚拟列的示例

《mysql查询使用_rowid虚拟列的示例》MySQL中,_rowid是InnoDB虚拟列,用于无主键表的行ID查询,若存在主键或唯一列,则指向其,否则使用隐藏ID(不稳定),推荐使用ROW_NUM... 目录1. 基本查询(适用于没有主键的表)2. 检查表是否支持 _rowid3. 注意事项4. 最佳实