Jetpack 之 ViewModel 组件介绍

简介: ViewModel 是介于 View(视图)和 Model(数据模型)之间的一个东西。它起到了桥梁的作用,使视图和数据既能够分离开,也能够保持通信。

本文目录

一、什么是 ViewModel

ViewModel 是介于 View(视图)和 Model(数据模型)之间的一个东西。它起到了桥梁的作用,使视图和数据既能够分离开,也能够保持通信。

ViewModel 将页面所需要的数据从页面中剥离出来,页面只需要处理用户交互和展示数据。

ViewModel 一般是通过 LiveData 或 DataBinding 两种方式来通知页面数据发生变化,更新 UI。关于 LiveData 和 DataBinding 我们在后面的文章会介绍,这里知道有这两种方式即可。

二、ViewModel 的生命周期

ViewModel 总是随着 Activity/Fragment 的创建而创建,随着 Activity/Fragment 的销毁而销毁。

不过,ViewModel 的生命周期是独立于配置变化的。如屏幕旋转所导致的 Activity 重建,并不会影响 ViewModel 的生命周期,重建后的 Activity 会重新连接到现有的 ViewModel。

Tips:配置变更主要是指:横竖屏切换、分辨率调整、权限变更、系统字体样式变更、启用多窗口模式...

三、ViewModel 的基本使用方法

步骤一:添加依赖

def lifecycle_version = "2.2.0"

// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"

最新版本号请查看:LifeCycle

步骤二:自定义 TimerViewModel 类,继承 ViewModel

public class TimerViewModel extends ViewModel {
   
   

    /**
     * 清理资源
     */
    @Override
    protected void onCleared() {
   
   
        super.onCleared();
        timer.cancel();
    }
}

ViewModel 本身是一个抽象类,其中只有一个 onCleared 方法,当 ViewModel 不再被需要,即与之相关的 Activity 都被销毁时,系统会调用该方法。我们可以在该方法中执行一些资源释放的相关操作。

步骤三

前文提到,ViewModel 最重要的作用是将视图与数据分离,并独立于 Activity 的重建,为了验证这一点,我们在 ViewModel 中创建一个计时器 Timer,每隔 1s,通过接口 OnTimeChangeListener 通知它的调用者(实际上通过接口的方式通知不是很好,更好的方式是通过 LiveData 组件来实现)。

public class TimerViewModel extends ViewModel {
   
   
    private Timer timer;
    private int currentSecond;

    /**
     * 开始计时
     */
    public void startTiming() {
   
   
        if (timer == null) {
   
   
            currentSecond = 0;
            timer = new Timer();
            TimerTask timerTask = new TimerTask() {
   
   
                @Override
                public void run() {
   
   
                    currentSecond++;
                    if (onTimeChangeListener != null) {
   
   
                        onTimeChangeListener.onTimeChanged(currentSecond);
                    }
                }
            };
            timer.schedule(timerTask, 1000, 1000);
        }
    }

    /**
     * 通过接口的方式,完成对调用者的通知
     * 实际上这种方式不是很友好,更好的方式是通过LiveData组件来实现
     */
    public interface OnTimeChangeListener {
   
   
        void onTimeChanged(int second);
    }

    private OnTimeChangeListener onTimeChangeListener;

    public void setOnTimeChangeListener(OnTimeChangeListener onTimeChangeListener) {
   
   
        this.onTimeChangeListener = onTimeChangeListener;
    }

    /**
     * 清理资源
     */
    @Override
    protected void onCleared() {
   
   
        super.onCleared();
        timer.cancel();
    }
}

步骤四:在 TimerActivity 中监听 OnTimeChangeListener 发来的通知,并更新 UI。

ViewModel 的实例化过程,是通过 ViewModelProvider 来完成的。ViewModelProvider 会判断 ViewModel 是否存在,若存在直接返回,否则它会创建一个 ViewModel。

public class TimerActivity extends AppCompatActivity {
   
   
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_timer);
        initComponent();
    }

    private void initComponent() {
   
   
        textView = findViewById(R.id.textView);
        TimerViewModel timerViewModel = new ViewModelProvider(this).get(TimerViewModel.class);
        timerViewModel.setOnTimeChangeListener(new TimerViewModel.OnTimeChangeListener() {
   
   
            @Override
            public void onTimeChanged(int second) {
   
   
                runOnUiThread(new Runnable() {
   
   
                    @Override
                    public void run() {
   
   
                        textView.setText("TIME:" + second);
                    }
                });
            }
        });
        timerViewModel.startTiming();
    }
}

步骤五:运行项目,并且旋转屏幕,看看计时器有没有停止

当旋转屏幕,Activity 重建时,计时器并没有停止。

四、ViewModel 与 AndroidViewModel

为了避免内存泄漏,我们在使用 ViewModel 时,不能将任何类型的 Context 或含有 Context 引用的对象传入 ViewModel。但是如果希望在 ViewModel 中使用 Context 的话该怎么办呢?

可以使用 AndroidViewModel ,它继承自 ViewModel,并接收 Application 作为 Context。

五、ViewModel 与 onSaveInstanceState() 对比

对于页面数据的保存和恢复,onSaveInstanceState() 方法同样可以解决屏幕旋转带来的数据丢失问题,那么我们是不是就没有必要使用 ViewModel 了呢?

注意,onSaveInstanceState() 方法只能保存少量的、能支持序列化的数据,而 ViewModel 没有这个限制,ViewModel 能支持页面中所有的数据。

同样需要注意的是,ViewModel 不支持数据的持久化,当界面被彻底销毁时,ViewModel 及其持有的数据就不存在了,但是 onSaveInstanceState() 方法没有这个限制,它可以持久化页面的数据。

可见,onSaveInstanceState() 方法有其特殊的用途,二者不可以混淆。

名称 保存数据的类型 是否支持持久化
ViewModel 只能保存少量的、能支持序列化的数据
onSaveInstanceState() 支持页面中所有的数据

六、使用 ViewModel 需要注意的地方

  1. ViewModel 的唯一职责是管理页面需要的数据(即 UI 需要的数据)。它不应该访问你的 View 结构,也不能持有 Activity/Fragment 的引用。
  2. 在使用 ViewModel 的过程中,千万不要将任何类型的 Context 或带有 Context 引用的对象传入 ViewModel ,因为这样做可能会引发内存泄漏。如果一定要在 ViewModel 中使用 Context,那么建议使用 ViewModel 的子类 AndroidViewModel。
相关文章
|
6月前
|
存储 设计模式 数据库
构建高效的安卓应用:探究Android Jetpack架构组件
【4月更文挑战第20天】 在移动开发的世界中,构建一个既高效又可维护的安卓应用是每个开发者追求的目标。随着Android Jetpack的推出,Google为开发者提供了一套高质量的库、工具和指南,以简化应用程序开发流程。本文将深入探讨Jetpack的核心组件之一——架构组件,并展示如何将其应用于实际项目中,以提升应用的响应性和稳定性。我们将通过分析这些组件的设计原则,以及它们如何协同工作,来揭示它们对于构建现代化安卓应用的重要性。
|
6月前
|
Android开发 开发者
什么是Android Jetpack,它包括哪些组件?
什么是Android Jetpack,它包括哪些组件?
194 0
|
6月前
|
前端开发 测试技术 API
Jetpack MVVM 七宗罪之六:ViewModel 接口暴露不合理
Jetpack MVVM 七宗罪之六:ViewModel 接口暴露不合理
85 0
|
6月前
|
XML 前端开发 IDE
在 Compose 中使用 Jetpack 组件库
在 Compose 中使用 Jetpack 组件库
351 0
|
安全 API Android开发
Jetpack架构组件库-Jetpack入门介绍
Jetpack架构组件库-Jetpack入门介绍
146 0
|
1月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
40 6
|
5月前
|
JavaScript Java Android开发
kotlin安卓在Jetpack Compose 框架下跨组件通讯EventBus
**EventBus** 是一个Android事件总线库,简化组件间通信。要使用它,首先在Gradle中添加依赖`implementation 'org.greenrobot:eventbus:3.3.1'`。然后,可选地定义事件类如`MessageEvent`。在活动或Fragment的`onCreate`中注册订阅者,在`onDestroy`中反注册。通过`@Subscribe`注解方法处理事件,如`onMessageEvent`。发送事件使用`EventBus.getDefault().post()`。
|
4月前
|
XML 存储 API
Jetpack初尝试 NavController,LiveData,DataBing,ViewModel,Paging
Jetpack初尝试 NavController,LiveData,DataBing,ViewModel,Paging
|
6月前
|
前端开发 Android开发
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
|
6月前
|
存储 数据库 Android开发
构建高效安卓应用:采用Jetpack架构组件优化用户体验
【4月更文挑战第12天】 在当今快速发展的数字时代,Android 应用程序的流畅性与响应速度对用户满意度至关重要。为提高应用性能并降低维护成本,开发者需寻求先进的技术解决方案。本文将探讨如何利用 Android Jetpack 中的架构组件 — 如 LiveData、ViewModel 和 Room — 来构建高质量的安卓应用。通过具体实施案例分析,我们将展示这些组件如何协同工作以实现数据持久化、界面与逻辑分离,以及确保数据的即时更新,从而优化用户体验并提升应用的可维护性和可测试性。