Android Jetpack架构组件 ViewModel详解

 更新时间:2020年07月14日 14:22:28   作者:黄林晴  
这篇文章主要介绍了Android Jetpack架构组件 ViewModel详解,ViewModel类让数据可在发生屏幕旋转等配置更改后继续存在,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的资料请关注脚本之家其它相关文章!

相关文章

  • Android开发实现广告无限循环功能示例

    Android开发实现广告无限循环功能示例

    这篇文章主要介绍了Android开发实现广告无限循环功能,结合完整实例形式分析了Android广告图片轮播功能的具体实现步骤与相关功能、布局等操作技巧,需要的朋友可以参考下
    2017-11-11
  • Android中实现下载和解压zip文件功能代码分享

    Android中实现下载和解压zip文件功能代码分享

    这篇文章主要介绍了Android中实现下载和解压zip文件功能代码分享,本文直接给出了实现代码,需要的朋友可以参考下
    2015-03-03
  • Android普通对话框用法实例分析

    Android普通对话框用法实例分析

    这篇文章主要介绍了Android普通对话框用法,以实例形式较为详细的分析了Android对话框的创建技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-09-09
  • android生命周期深入分析(一)

    android生命周期深入分析(一)

    Android 程序的生命周期是由系统控制而非程序自身直接控制,本文将详细介绍,需要的朋友可以参考下
    2012-12-12
  • Android开发之RecyclerView控件

    Android开发之RecyclerView控件

    本文给大家介绍的是Android开发中常用的RecyclerView控件的使用方法以及简单的特性,有需要的小伙伴可以参考下
    2016-02-02
  • Android 中使用RecyclerView实现底部翻页

    Android 中使用RecyclerView实现底部翻页

    这篇文章主要介绍了Android 中使用RecyclerView实现底部翻页功能,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-11-11
  • Android ListView UI组件使用说明

    Android ListView UI组件使用说明

    这篇文章主要介绍了Android ListView UI组件使用说明,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Android Apk反编译及加密教程

    Android Apk反编译及加密教程

    这篇文章主要为大家介绍了Android Apk反编译及加密教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-03-03
  • Android开发实现自定义水平滚动的容器示例

    Android开发实现自定义水平滚动的容器示例

    这篇文章主要介绍了Android开发实现自定义水平滚动的容器,涉及Android滚动容器的事件响应、属性运算与修改相关操作技巧,需要的朋友可以参考下
    2017-10-10
  • Retrofit实现图文上传至服务器

    Retrofit实现图文上传至服务器

    本文主要介绍了Retrofit实现图文上传至服务器的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-03-03

最新评论