Android Jetpack架构组件 ViewModel详解

前言

前面两篇文章我们已经学习了Lifecycle和DataBind,本篇文章我们来学习Jetpack系列中比较重要的ViewModel,Jetpack的很多很多组件都是搭配使用的,所以单独的知识点可能会有些”无意义“但却是我们项目实战的基础!

ViewModel的使用

ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel类让数据可在发生屏幕旋转等配置更改后继续存在。这句话很好理解,还记得我们在讲解Lifecycle的时候 举的例子吗,我们还是使用那个例子,如果你还没看过,可移步至:

Android Jetpack系列之Lifecycle

我们再回顾一次需求:

在Activity 可见的时候,我们去做一个计数功能,每隔一秒 将计数加1 ,当Activity不可见的时候停止计数,当Activity被销毁的时候 将计数置为0,这里我们在Activity被销毁的时候不再将count置为0,WorkUtil代码如下所示:

public class WorkUtil implements LifecycleObserver {

 private static final String TAG = "WorkUtil";

 private boolean whetherToCount = true;

 private int count = 0;

 @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
 public void start() {
 new Thread(new Runnable() {
  @Override
  public void run() {
  while (whetherToCount) {
   try {
   Thread.sleep(1000);
   count++;
   Log.d(TAG, "start: " + count);
   } catch (InterruptedException e) {
   e.printStackTrace();
   }
  }
  }
 }).start();
 }

 @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
 public void onStop() {
 whetherToCount = false;
 Log.d(TAG, "onStop: ");
 }

 @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
 public void onDestory() {
 }
}

我们运行程序,在计数的过程中 使屏幕旋转,运行结果如下所示:

我们可以看到,当屏幕旋转的时候,由于生命周期发生了改变,导致数据被销毁,所以计数器的计数又从初始值开始计数了,那么我们如何解决这个问题呢,你肯定会说,缓存呀,重写onSabeInstanceState()方法等等,都可以但是都不够优雅,那么如何优雅的来解决这个问题呢,这就是我们的今天的主角  ViewModel。

ViewModel的使用

我们新建Main3ActivityModel 继承自 ViewModel,在Main3ActivityModel中定义count变量 如下所示:

public class Main3ActivityViewModel extends ViewModel {

 public int count = 0;

}

没错,就是这么简单,我们只要保证计数的变量是这个model中的变量,就可以解决我们上面的问题

我们通过ViewModelProviders来获取ViewModel对象

main3ActivityViewModel = ViewModelProviders.of(this).get(Main3ActivityViewModel.class);

但是这个方法已经过时了,替代方法是

main3ActivityViewModel = new ViewModelProvider(this).get(Main3ActivityViewModel.class);

为了让WorkUtil使用Model中的变量,所以我们要将ViewModel 传递过去,在WorkUtil中新增一个构造方法

private Main3ActivityViewModel main3ActivityViewModel;

public WorkUtil(Main3ActivityViewModel main3ActivityViewModel) {
 this.main3ActivityViewModel = main3ActivityViewModel;
}

我们将WorkUtil中的计数变量count 改为 main3ActivityViewModel.count,如下所示:

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void start() {
 new Thread(new Runnable() {
 @Override
 public void run() {
  while (whetherToCount) {
  try {
   Thread.sleep(1000);
   main3ActivityViewModel.count++;
   Log.d(TAG, "start: " + main3ActivityViewModel.count);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  }
 }
 }).start();
}

main3Activity中在lifecycle中传参:

getLifecycle().addObserver(new WorkUtil(main3ActivityViewModel));

再次运行程序,运行过程中旋转手机屏幕,打印如下所示:

我们可以看到,在屏幕旋转之后,计数器的计数保留了,那么viewModel是如何做到的呢,这是因为ViewModel 对象存在的时间比视图或 LifecycleOwners 的特定实例存在的时间更长,ViewModel的生命周期如下图所示(摘自官网) 

向ViewModel传参

当前计数的需求是从0开始计时,我们现在修改需求如下,使用用户输入的数字为起点开始计数,这样的话ViewModel中的count就不是0了,而是传入的参数,我们在Main3Activity中定义变量inputCount 来模拟用户输入的数字

private int inputCount = 100;

在Main3ViewModel中添加构造方法

public int count = 0;

public Main3ActivityViewModel(int count) {
 this.count = count;
}

看到这里,你可能会说,我们直接new一个传过去不就行了吗,请记住这是万万不行的,因为如果我们使用直接实例化来创建ViewModel,那么ViewModel的生命周期就受Activity的影响了,所以为什么我们只能通过ViewModelProvider来获取ViewModel的实例。

我们需要借助ViewModelProvider.Factory来实现传参,新建Main3ActivityViewModelFactor继承自 ViewModelProvider.Factory,重写其onCreate方法,如下所示:

public class Main3ActivityViewModelFactory implements ViewModelProvider.Factory {

 @NonNull
 @Override
 public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
 return null;
 }
}

添加一个构造方法,并在create中创建VideModel实例

private int count;

public Main3ActivityViewModelFactory(int count) {
 this.count = count;
}

@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
 return (T) new Main3ActivityViewModel(count);
}

在Activity中获取实例的时候 采用如下方法

main3ActivityViewModel = new ViewModelProvider(this,new Main3ActivityViewModelFactory(inputCount)).get(Main3ActivityViewModel.class);

运行程序,打印结果如下所示: 

如此一来 我们就实现ViewModel传递参数了~

以上就是Android Jetpack架构组件 ViewModel详解的详细内容,更多关于Android Jetpack架构组件 ViewModel的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android中butterknife的使用与自动化查找组件插件详解

    前言 Android开发中经常使用findViewById来获取控件然后进行一些列操作,当控件太多的时候代码就非常臃肿,今天就来学习一个新的开源库ButterKnife,真的可以帮助我们高效,快捷的开发,让我们的代码更加简洁. 首先我们来把ButterKnife集成在我们的项目中:ButterKnife的GitHub官方地址:github.com/JakeWharton- 一.集成分为了两部分: 1.仅仅在App主工程使用: 在App的 build.gradle 中添加如下代码: android

  • Android列表组件ListView使用详解之动态加载或修改列表数据

    在使用ListView组件来显示列表数据时,有的时候我们需要改变列表中的数据,有以下方法: 1.重新给ListView组件设置适配器 这种方法重新创建了ListView,效率不好. 2.使用适配器中的方法 /** * Notifies the attached observers that the underlying data has been changed * and any View reflecting the data set should refresh itself. */ pu

  • Android框架组件Lifecycle的使用详解

    1.前言 Lifecycle是Google推出的一系列的框架组件的其中一个,主要是用来感知Activity和Fragment的生命周期. 本文主要介绍如何使用Lifecycle. 2.一个常见的开发例子 public class TestActivity extends Activity{ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceSta

  • Android四大组件之Activity详解

    一.Activity的生命周期 首先,我们来了解一下Activity典型的生命周期 一个Activity从启动到结束会以如下顺序经历整个生命周期: onCreate()->onStart()->onResume()->onPause()->onStop()->onDestory().包含了六个部分,还有一个onRestart()没有调用, 下面就来一一介绍 onCreate():当 Activity 第一次创建时会被调用.当 Activity 第一次创建时会被调用.这是生命周

  • Android使用开源组件PagerBottomTabStrip实现底部菜单和顶部导航功能

    PagerBottomTabStrip 是一个基本按谷歌Material Design规范完成的安卓底部导航栏控件 官方设计规范:https://www.google.com/design/spec/components/bottom-navigation.html 1.前言 (1)底部选择菜单功能应该是大多app都会用到的,实现方式也有很多种,比较笨的方法可以自定义一个xml,下方布局样式,每次点击不同按钮时跳转到不同activity,这个activity重新加载一下底部菜单 (2)今天介绍一

  • Android四大组件之Service详解

    一.Service简介 Service是Android程序中四大基础组件之一,它和Activity一样都是Context的子类,只不过它没有UI界面,是在后台运行的组件. Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务.Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作. 二.Serv

  • Android开发之组件GridView简单使用方法示例

    本文实例讲述了Android开发之组件GridView简单使用方法.分享给大家供大家参考,具体如下: 案例:简单的图片浏览器,保存图片到相册 保存图片到相册 方法代码:https://www.jb51.net/article/158668.htm 废话不多说先上效果: 具体实现: 首先是布局文件: 1.一个GridView(展示所有的图片) 2.一个ImageView(放选中的图片) <?xml version="1.0" encoding="utf-8"?&

  • Android四大组件之BroadcastReceiver详解

    BroadcastReceiver(广播接收器),在Android开发中,BroadcastReceiver的应用场景非常多,属于Android四大组件之一. Android 广播分为两个角色:广播发送者.广播接收者 一. 作用 用于监听 / 接收 应用发出的广播消息,并做出响应 应用场景: 不同组件之间通信(包括应用内 / 不同应用之间) 与 Android 系统在特定情况下的通信(如当电话呼入时.网络可用时) 多线程通信 二.实现原理 Android中的广播使用了设计模式中的观察者模式:基于

  • android自定义组件实现仪表计数盘

    前几天开发公司项目,有个地方要做一个分数的仪表盘,根据分数跑分,(设计的人估计是看到招商银行App的账号总览) 网上好像找不到类似的组件,那就只能自己开发啦.趁着空余时间,把组件进行了一些改进,并封装成依赖库,分享给大家 效果展示 一款颜色,文字弧度大小,仪表角度都可以自定义的组件 项目集成:MeterView 项目目录-->build.gradle allprojects { repositories { ... maven { url 'https://jitpack.io' } } } a

  • Android Jetpack架构组件 ViewModel详解

    前言 前面两篇文章我们已经学习了Lifecycle和DataBind,本篇文章我们来学习Jetpack系列中比较重要的ViewModel,Jetpack的很多很多组件都是搭配使用的,所以单独的知识点可能会有些"无意义"但却是我们项目实战的基础! ViewModel的使用 ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据.ViewModel类让数据可在发生屏幕旋转等配置更改后继续存在.这句话很好理解,还记得我们在讲解Lifecycle的时候 举的例子吗,我们还是使用那

  • Android Jetpack架构组件Lifecycle详解

    前言 Lifecycle是Jetpack架构组件中用来感知生命周期的组件,使用Lifecycles可以帮助我们写出和生命周期相关更简洁更易维护的代码. 生命周期 生命周期这个简单而又重要的知识相信大家早已耳熟能详.假设我们现在有这样一个简单需求: 这个需求只是一个实例,在真实的开发中当然不可能有这样的需要: 在Activity 可见的时候,我们去做一个计数功能,每隔一秒 将计数加1 ,当Activity不可见的时候停止计数,当Activity被销毁的时候 将计数置为0 OK,So easy~ ,

  • Android Jetpack架构中ViewModel接口暴露的不合理探究

    目录 暴露 Mutable 状态 暴露 Suspend 方法 在 Jetpack 架构规范中, ViewModel 与 View 之间应该遵循单向数据流的通信方式,Events 永远从 View 流向 VM ,而 State 从 VM 流向 View. 如果 ViewModel 对 View 暴露了不适当的接口类型,则会破坏单向数据流的形成.不适当的接口类型常见于以下两点: 暴露 Mutable 状态 暴露 Suspend 方法 暴露 Mutable 状态 ViewModel 对外暴露的数据状态

  • Android编程自定义组件实例详解

    本文实例讲述了Android编程自定义组件.分享给大家供大家参考,具体如下: 在Android中,所有的UI界面都是由View类和ViewGroup类及其子类组合而成.其中,View类是所有UI组件的基类,而ViewGroup类是容纳这些UI组件的容器. 其本身也是View类的子类. 在实际开发中,View类还不足以满足程序所有的需求.这时,便可以通过继承View类来开发自己的组件. 开发自定义组件的步骤: 1.创建一个继承android.view.View类的View类,并且重写构造方法. 2

  • Android Jetpack导航组件Navigation创建使用详解

    目录 引言 依赖项 创建导航图 导航宿主 导航到目的地 传递参数 NavigationUI 多模块导航 引言 导航是指支持用户导航.进入和退出应用中不同内容片段的交互.Android Jetpack 的导航组件可实现导航,无论是简单的按钮点击,还是应用栏和抽屉式导航栏等更为复杂的模式,该组件均可应对. 依赖项 def nav_version = "2.5.2" implementation "androidx.navigation:navigation-fragment-kt

  • Android架构发展进化详解

    目录 一.MVC架构 1.概述 2.例子 二.MVP架构 1.概述 2.例子 三.MVVM架构 1.概述 2.例子 四.Clean架构 1.概述 2.例子 五.MVI架构 1.概述 2.例子 六.总结 1.从MVC架构到MVI架构 2.从clean code到clean coder 3.MVI架构之后 一.MVC架构 1.概述 MVC架构是第一个应用于Android开发的成熟架构,由Model.View.Controller三部分组成: Model:负责数据的存储及相关逻辑. View:负责界面

  • Android实现MVVM架构数据刷新详解流程

    目录 效果图 示例结构图 代码解析 导入dataBinding 实体类 xml视图 VM 绑定视图与数据层 效果图 示例结构图 代码解析 导入dataBinding dataBinding{ enabled = true } 实体类 继承BaseObservable public class Sensor extends BaseObservable 为字段添加@Bindable @Bindable public String getTmpValue() { return tmpValue; }

  • Android性能优化之RecyclerView分页加载组件功能详解

    目录 引言 1 分页加载组件 1.1 功能定制 1.2 手写分页列表 1.3 生命周期管理 2 github 引言 在Android应用中,列表有着举足轻重的地位,几乎所有的应用都有列表的身影,但是对于列表的交互体验一直是一个大问题.在性能比较好的设备上,列表滑动几乎看不出任何卡顿,但是放在低端机上,卡顿会比较明显,而且列表中经常会伴随图片的加载,卡顿会更加严重,因此本章从手写分页加载组件入手,并对列表卡顿做出对应的优化 1 分页加载组件 为什么要分页加载,通常列表数据存储在服务端会超过100条

  • Vue之vue-tree-color组件实现组织架构图案例详解

    目录 npm 安装loader Import Plugins 开始 排列方式 折叠展示 点击节点 其他功能 npm # use npm npm install vue-tree-color 安装loader npm install --save-dev less less-loader Import Plugins import Vue from 'vue' import Vue2OrgTree from 'vue-tree-color' Vue.use(Vue2OrgTree) 开始 因为已经

  • Android Binder 通信原理图文详解

    目录 前言 1. Binder的作用 2. 进程与Binder驱动如何通信 3. ServiceManager进程的作用 Binder Client.Binder Server.ServiceManager关系 ServiceManager注册进Binder 4. 进程添加服务到ServiceManager的流程 其它进程找到SM 添加服务到ServiceManager BBinder作用 5. 进程从ServiceManager获取服务的流程 其它进程找到SM 从ServiceManager获

随机推荐