Android Jetpack 应用指南(二) - ViewModel

简介:

前言

上一篇文章简要概述了LiveData及其简单使用,本篇将会简要讲述AAC的另一个核心组件ViewModel。

与上一篇文章相同,本篇同样是ViewModel的初探,会用尽可能简洁的方式来了解ViewModel,让我们对ViewModel有一个初步印象,不会长篇大论或者源码轰炸,导致干货太多引起阅读困难。

目录

  • ViewModel简介
  • ViewModel生命周期
  • ViewModel使用教程
  • ViewModel注意事项

正文

ViewModel简介

ViewModel是用来保存应用UI数据的类,它会在配置变更(Configuration Change)后继续存在。

为什么需要在Android开发中引入ViewModel类呢?

原因有以下几点:

1.在Android开发中,我们将变量、逻辑和数据都放置在Activity或Fragment中,长此以往不仅导致了Activity和Fragment的代码难以维护,这也违反了单一责任原则。使用ViewModel来保存UI数据,可以分担一部分Activity与Fragment的责任,将原本不堪重负的UI控制器的责任进一步划分出去。

记住一点,任何时候activity或fragment只应该用来显示UI数据和接收用户互动,不要在其中保存、处理任何数据。

2.Activity或Fragment这类应用组件都会受到Configuration Change的影响,例如屏幕旋转的时候,Ativity会被销毁重建,如果数据没有正确的保存并恢复,就有可能丢失,导致UI显示异常甚至是崩溃。将应用所有的UI数据保存在ViewModel中,而不是activity中,这样就能确保数据不会受到 Configuration Change的影响。

ViewModel生命周期

当ViewModel的实例生成后,它会在内存中一直存在,直到它的LifeCycle彻底消失。下面用一张引用自官方文档的图,来说明ViewModel的生命周期。
ViewModel的生命周期
从图中可以看出,在Activity的生命周期onCreate()下创建一个ViewModel,当屏幕旋转(activity rotated)时,Activity会销毁并重新创建,但是ViewModel一直存在,直到Activity结束并被彻底销毁。这意味着ViewModel不会因为它的创建者的配置变化而被销毁。

需要注意的是当Activity的回调onDestroy()时并不代表ViewModel会被销毁。

ViewModel使用流程

ViewModel的使用大致有以下2个步骤:

1.创建一个任意名称的类,一般使用XXXViewModel,继承ViewModel类,然后将原本放置在Activity或Fragment中的变量实例,全部移到ViewModel中。如果和LiveData一起使用的话,就可以创建一个响应式的界面。

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

2.在Activity或Fragment通过ViewModel Provider的框架实用类来获取ViewModel。

class MasterFragment : Fragment() {

    private lateinit var itemSelector: Selector

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this).get(SharedViewModel::class.java)
        } ?: throw Exception("Invalid Activity")
        itemSelector.setOnClickListener { item ->
            // Update the UI
        }
    }
}

class DetailFragment : Fragment() {

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this).get(SharedViewModel::class.java)
        } ?: throw Exception("Invalid Activity")
        model.selected.observe(this, Observer<Item> { item ->
            // Update the UI
        })
    }
}

上述代码中MasterFragment和DetailFragment中会创建一个完全相同的SharedViewModel实例,通过SharedViewModel的实例,MasterFragment和DetailFragment可以进行数据共享和通信。

使用这种方式有以下几个优点:

  • 1.Activity不需要做任何额外处理,也不需要了解ViewModel的交互方式。

  • 2.Fragment与Fragment有着独立的生命周期,相互之间互不影响,如果一个Fragment被替换了,另一个Fragment依然可以正常工作。

  • 3.Fragemnt之间除了需要连接同一个ViewModel外,不需要做额外的操作,即使一个Fragment被销毁,另一个Fragment也不会受到影响。

ViewModel注意事项

通过上述的简单介绍,我们知道了ViewModel强大之处,但是ViewModel在使用时,也存在一些需要注意的事项:

  • 1.任何时候都不要向ViewModel中传入Context对象

    因为Viewmodel的生命周期比它相关联的Activity和Fragment要长,当你在Viewmodel中存储了一个context,当activity被销毁时,ViewModel就会产生内存泄漏。

  • 2.使用AndroidViewModel延长ViewModel的生命周期

    多数情况下,你并不需要延长ViewModel的生命周期。但是某些情况下,你确实需要一个生命周期更长的ViewModel时,可以使用AndroidViewModel,它的生命周期于Application保持一致,也可以在AndroidViewModel中直接使用application的引用。

  • 3.ViewModel并不能取代onSaveInstanceState

    虽然ViewModel和onSaveInstanceState都可以存储数据用于恢复UI界面,但是二者还是存在这以下不同:

    1.ViewModel可以度过配置变更,可以存储大量数据。

    2.onSaveInstanceState可以度过配置变更和进程关闭,只能存储有限的数据

    也就是说当进程被关闭时,viewModel将会被销毁,而onSaveInstanceState将不会受到影响,一般会在viewModel中存储全部UI数据,而onSvaeInstanceState则只存储可以还原UI状态的最少数据。

总结

本篇文章简述了AAC的另一个核心组件ViewModel,本文的定位是初探,所以ViewModel中一个很重要的Fractory方法,还没有介绍,这部分会在后续的AAC实战中再做讲解。下篇文章,再来我么继续来探索AAC的另一个组件Navigation。

目录
相关文章
|
18天前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
82 4
|
1月前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!
|
1月前
|
存储 搜索推荐 Java
打造个性化安卓应用:从设计到实现
【10月更文挑战第30天】在数字化时代,拥有一个个性化的安卓应用不仅能够提升用户体验,还能加强品牌识别度。本文将引导您了解如何从零开始设计和实现一个安卓应用,涵盖用户界面设计、功能开发和性能优化等关键环节。我们将以一个简单的记事本应用为例,展示如何通过Android Studio工具和Java语言实现基本功能,同时确保应用流畅运行。无论您是初学者还是希望提升现有技能的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧。
|
1月前
|
搜索推荐 开发工具 Android开发
打造个性化Android应用:从设计到实现的旅程
【10月更文挑战第26天】在这个数字时代,拥有一个能够脱颖而出的移动应用是成功的关键。本文将引导您了解如何从概念化阶段出发,通过设计、开发直至发布,一步步构建一个既美观又实用的Android应用。我们将探讨用户体验(UX)设计的重要性,介绍Android开发的核心组件,并通过实际案例展示如何克服开发中的挑战。无论您是初学者还是有经验的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧,帮助您在竞争激烈的应用市场中脱颖而出。
|
1月前
|
算法 Java 数据库
Android 应用的主线程在什么情况下会被阻塞?
【10月更文挑战第20天】为了避免主线程阻塞,我们需要合理地设计和优化应用的代码。将耗时操作移到后台线程执行,使用异步任务、线程池等技术来提高应用的并发处理能力。同时,要注意避免出现死循环、不合理的锁使用等问题。通过这些措施,可以确保主线程能够高效地运行,提供流畅的用户体验。
45 2
|
2月前
|
Java API Android开发
安卓应用程序开发的新手指南:从零开始构建你的第一个应用
【10月更文挑战第20天】在这个数字技术不断进步的时代,掌握移动应用开发技能无疑打开了一扇通往创新世界的大门。对于初学者来说,了解并学习如何从无到有构建一个安卓应用是至关重要的第一步。本文将为你提供一份详尽的入门指南,帮助你理解安卓开发的基础知识,并通过实际示例引导你完成第一个简单的应用项目。无论你是编程新手还是希望扩展你的技能集,这份指南都将是你宝贵的资源。
68 5
|
2月前
|
移动开发 Dart 搜索推荐
打造个性化安卓应用:从零开始的Flutter之旅
【10月更文挑战第20天】本文将引导你开启Flutter开发之旅,通过简单易懂的语言和步骤,让你了解如何从零开始构建一个安卓应用。我们将一起探索Flutter的魅力,实现快速开发,并见证代码示例如何生动地转化为用户界面。无论你是编程新手还是希望扩展技能的开发者,这篇文章都将为你提供价值。
|
7月前
|
移动开发 安全 Android开发
构建高效Android应用:Kotlin协程的实践与优化策略
【5月更文挑战第30天】 在移动开发领域,性能优化始终是关键议题之一。特别是对于Android开发者来说,如何在保证应用流畅性的同时,提升代码的执行效率,已成为不断探索的主题。近年来,Kotlin语言凭借其简洁、安全和实用的特性,在Android开发中得到了广泛的应用。其中,Kotlin协程作为一种新的并发处理机制,为编写异步、非阻塞性的代码提供了强大工具。本文将深入探讨Kotlin协程在Android开发中的应用实践,以及如何通过协程优化应用性能,帮助开发者构建更高效的Android应用。
|
7月前
|
API 调度 Android开发
打造高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第27天】在移动开发领域,性能优化和响应速度是衡量应用质量的关键因素。随着Kotlin语言的普及,协程作为其核心特性之一,为Android开发者提供了一种全新的并发处理方式。本文深入探讨了Kotlin协程在Android应用开发中的优势,并通过实例演示如何在实际项目中有效利用协程提升应用性能和用户体验。
|
7月前
|
移动开发 Android开发 开发者
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第21天】在移动开发领域,性能优化和流畅的用户体验是至关重要的。随着Kotlin语言在Android平台的广泛采纳,其并发处理的强大工具—协程(Coroutines),已成为提升应用响应性和效率的关键因素。本文将深入分析Kotlin协程的核心原理,探讨其在Android开发中的优势,并通过实例演示如何有效利用协程来优化应用性能,打造更加流畅的用户体验。
70 4