使用Android Jetpack ViewModel

Basically, ViewModel is a part of the Android Architecture Components. One of the main goals of ViewModel object is serving data to the Android UI components such as activities or fragments, and separating the data processing logic from the UI. Another aspect of ViewModel is managing UI-related data in a lifecycle conscious way. This feature allows data to survive configuration changes like screen rotations. This essay aims to discuss ViewModel concepts, and also the required steps to implement ViewModel in Android applications.

基本上,ViewModel是Android体系结构组件的一部分。 ViewModel对象的主要目标之一是将数据提供给Android UI组件(例如活动或片段),并将数据处理逻辑与UI分离。 ViewModel的另一个方面是以生命周期意识的方式管理与UI相关的数据。 此功能使数据可以抵抗屏幕旋转等配置更改。 本文旨在讨论ViewModel概念,以及在Android应用程序中实现ViewModel所需的步骤。

概述与介绍 (Overview and Introduction)

The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations.

ViewModel类旨在以生命周期感知的方式存储和管理与UI相关的数据。 ViewModel类允许数据幸免于配置更改(例如屏幕旋转)。

Basically, ViewModels are objects that support data for UI components, and survive configuration changes. In fact, rotating your mobile phone is considered a configuration change. Configuration changes cause your whole activity to get recreated. If you do not properly save and restore data from the destroyed activity, you will lose that data. In addition, you will face some UI bugs or crashes. Thus, instead of storing all of your UI data in your activity, you should put it in the ViewModel. In this case, this helps with configuration changes; however, it is also a best practice for software design. In other words, one common pitfall when developing for Android is putting a lot of variables, logic, and data into your activities and fragments. This creates a large unmaintainable classes, and breaks the rule of single responsibility principle in SOLID principles. As a result, you can be able to use ViewModel to easily divide out that responsibility. The ViewModel will be responsible for holding all of the data that you want to show in your UI, and then the activity is only responsible for knowing how to show that data to the screen for receiving user interactions, but not for processing those data. Another significant point is that if your Android app loads and stores data, you can create a Repository class as explained in the Guide to App Architecture document by Google because your ViewModel should not be faced with excessive responsibilities.

基本上,ViewModels是支持UI组件数据并可以保留配置更改的对象。 实际上,旋转手机被视为配置更改。 配置更改会导致重新创建整个活动。 如果您没有正确地保存和恢复销毁活动中的数据,则将丢失该数据。 此外,您还会遇到一些UI错误或崩溃。 因此,您应该将其放在ViewModel中,而不是将所有UI数据存储在活动中。 在这种情况下,这有助于更改配置。 但是,这也是软件设计的最佳实践。 换句话说,为Android开发时,一个常见的陷阱是将很多变量,逻辑和数据放入您的活动和片段中。 这将创建大量无法维护的类,并打破了SOLID原则中的单一责任原则的规则。 因此,您可以使用ViewModel轻松划分该职责。 ViewModel将负责保存您希望在UI中显示的所有数据,然后该活动仅负责知道如何在屏幕上显示该数据以接收用户交互,而不负责处理这些数据。 另一个重要的意义是,如果您的Android应用加载并存储数据,则可以按照Google的《 App体系结构指南》文档中的说明创建一个Repository类,因为您的ViewModel不必承担过多的责任。

Image for post
Google documents Google文档提供

In other words, UI controllers such as activities and fragments are mainly intended to display UI data, react to user interactions, or handle OS communication like permission requests. Additionally, UI controllers can be responsible for loading data from a database or network connection. In fact, setting excessive responsibility to UI controllers can result in a single class, which tries to manage all of an app’s tasks by itself, instead of delegating work to other classes. Thus, setting excessive responsibility to the UI controllers in this way can make testing process much more difficult.

换句话说,诸如活动和片段之类的UI控制器主要用于显示UI数据,对用户交互做出React或处理OS通信(如权限请求)。 此外,UI控制器可以负责从数据库或网络连接中加载数据。 实际上,对UI控制器设置过多的责任可能会导致一个类,该类试图单独管理应用程序的所有任务,而不是将工作委派给其他类。 因此,以这种方式对UI控制器设置过多的责任会使测试过程变得更加困难。

ViewModel is a class that is responsible for preparing and managing the data for an Activity or a Fragment. It also handles the communication of the Activity / Fragment with the rest of the application (e.g. calling the business logic classes).

ViewModel是一个类,负责为Activity或Fragment准备和管理数据。 它还处理活动/片段与应用程序其余部分的通信(例如,调用业务逻辑类)。

Another important problem is that UI controllers (activities and fragments) frequently need to make asynchronous calls that may take some time to return the result. So, the UI controller needs to handle these calls, and make sure the system cleans them up after destroying to avoid some potential memory leaks. It is clear that this issue needs a lot of maintenance because an object is re-created for a configuration change, and this leads to waste of resources due to this repeated processes.

另一个重要的问题是UI控制器(活动和片段)经常需要进行异步调用,这可能需要一些时间才能返回结果。 因此,UI控制器需要处理这些调用,并确保系统在销毁后清除它们,以避免潜在的内存泄漏。 显然,此问题需要大量维护,因为重新创建对象以进行配置更改,并且由于此重复过程而导致资源浪费。

ViewModel’s only responsibility is to manage the data for the UI. It should never access your view hierarchy or hold a reference back to the Activity or the Fragment.

ViewModel的唯一责任是管理UI的数据。 它永远不应访问您的视图层次结构,也不应保留对活动或片段的引用。

实现ViewModel (Implementing ViewModel)

  1. Create a subclass of ViewModel

    创建ViewModel的子类

To create a ViewModel, you will need to extend the ViewModel class, and then you can put your UI-related instance variables that were previously in your activity into your ViewModel. For example:

要创建ViewModel,您需要扩展ViewModel类,然后可以将先前在您的活动中与UI相关的实例变量放入ViewModel中。 例如:

class UserViewModel: ViewModel() {val user = User(name = "", address = "")}

2. Set up ViewModel Provider in your activity’s onCreate

2. 在活动的onCreate中设置ViewModel Provider

Then, in your activity’s onCreate, you get the ViewModel from a framework utility class that is called ViewModel Provider. Notice the ViewModel Provider takes an activity instance. This is the mechanism that allows you to rotate the device, get a technically new activity instance, but always make sure that activity instance is connected with the same ViewModel.

然后,在活动的onCreate中,从称为ViewModel Provider的框架实用工具类中获取ViewModel。 注意,ViewModel Provider采用了一个活动实例。 通过这种机制,您可以旋转设备,获取技术上新的活动实例,但始终确保活动实例与同一ViewModel连接。

override fun onCreate(savedInstanceState: Bundle?) {

val userViewModel =
ViewModelProviders.of(this).get(UserViewModel)::class.java)
userViewModel.user.name = "John"

}

By using the ViewModel instance, you can be able to use Getters and Setters to access UI data from your activity. If you want to customize the default constructor, which currently no parameters, you can use a ViewModel Factory for implementing a custom constructor.

通过使用ViewModel实例,您可以使用Getter和Setter来访问活动中的UI数据。 如果要自定义默认构造函数(当前没有参数),则可以使用ViewModel Factory来实现自定义构造函数。

3. Use LiveData and Data Binding with your ViewModel

3. 将LiveData和数据绑定与ViewModel一起使用

Currently, this is the simplest form of a ViewModel, but the ViewModel class is also designed to work appropriately with LiveData and Data Binding libraries. By using all of these approaches, you can create a reactive UI for your Android app, which indicates that your UI will automatically updates whenever the data changes.

当前,这是ViewModel的最简单形式,但是ViewModel类也被设计为与LiveDataData Binding库一起使用。 通过使用所有这些方法,您可以为Android应用创建React式UI,该UI指示只要数据更改,UI就会自动更新。

The Data Binding Library is a support library that allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically.

数据绑定库是一个支持库,使用该库,您可以使用声明性格式而非编程方式将布局中的UI组件绑定到应用程序中的数据源。

ViewModel + LiveData + Data Binding = Reactive UI

ViewModel + LiveData +数据绑定=响应式UI

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.

LiveData是可观察的数据持有者类。 与常规的可观察数据不同,LiveData具有生命周期感知功能,这意味着它尊重其他应用程序组件(例如活动,片段或服务)的生命周期。 这种意识确保LiveData仅更新处于活动生命周期状态的应用程序组件观察者。

This assumes all of your data in your ViewModel, which you plan to represent on screen is packed in LiveData as follows:

假定您打算在屏幕上表示的ViewModel中的所有数据都打包在LiveData中,如下所示:

class UserViewModel: ViewModel() {  private val _user MutableLiveData<User>()  val user : LiveData<User>
get() = _user

}

Then, you should set up Data Binding. For instance, the XML with the Data Binding layout tag and variable tag for your ViewModel are as below:

然后,您应该设置数据绑定。 例如,ViewModel的带有数据绑定布局标签和变量标签的XML如下:

<layout>   
<data>
<variable>
name="viewmodel"
type="android.example.com.UserViewModel"/>
</data>
<.../>
</layout>

After completing this step, you should add these lines of codes to your activity’s onCreate as below:

完成此步骤后,您应该将这些代码行添加到活动的onCreate中,如下所示:

override fun onCreate(savedInstanceState: Bundle?) {

// Rest of the onCreate method...

val binding = ActivityMainBinding.inflate(layoutInflater)
binding.viewmodel = userViewModel
binding.setLifecycleOwner(this)
setContentView(binding.root)

}

In above code setLifecycleOwner() method allows the binding to observe your LiveData objects in the ViewModel, and this helps the binding update whenever the LiveData changes.

在上面的代码中,setLifecycleOwner()方法允许绑定在ViewModel中观察您的LiveData对象,这有助于在LiveData更改时更新绑定。

ViewModel的生命周期 (The lifecycle of a ViewModel)

In the below diagram, you can be able to see the lifecycle of an Activity, which faces a rotation. The lifetime of the ViewModel is displayed next to the associated Activity lifecycle. As a matter of fact, ViewModel can be easily used with both Fragments and Activities. The ViewModel exists from when you request a ViewModel firstly (in activity’s onCreate) until the activity is finished and destroyed. Thus, onCreate() could be called several times during the life of an Activity.

在下图中,您可以看到面对旋转的Activity的生命周期。 ViewModel的生命周期显示在关联的Activity生命周期旁边。 实际上,ViewModel可以轻松地与Fragment和Activity一起使用。 从第一次请求ViewModel(在活动的onCreate中)到活动完成并销毁为止,ViewModel就存在。 因此,在Activity的生存期内,onCreate()可以被调用多次。

Image for post
Google documents Google文档提供

ViewModel和onSaveInstanceState之间的区别 (Differences between ViewModel and onSaveInstanceState)

Fundamentally, although ViewModel is designed to be applied in addition to onSaveInstanceState as an another option, there are some differences can be mentioned clearly. ViewModels do not survive process shutdown because of resource restrictions, but onSaveInstance bundles do this task. ViewModel is a great choice for storing huge amounts of data; whereas, onSaveInstanceState bundles is not an appropriate option for that purpose. ViewModels are utilized to store as much UI data as possible. Therefore, that data does not need to be reloaded or regenerated during a configuration changes. onSaveInstanceState, on the other hand, should store the smallest amount of data needed to restore the UI state if the process is shut down by the framework. For instance, you might store all of the user’s data within the ViewModel while just store the user’s database ID in onSaveInstanceState.

从根本上讲,尽管ViewModel被设计为除了onSaveInstanceState之外还作为另一个选项被应用,但是还是有一些明显的区别。 由于资源限制,ViewModels在进程关闭后无法生存,但是onSaveInstance捆绑包可以执行此任务。 ViewModel是用于存储大量数据的绝佳选择。 但是,onSaveInstanceState捆绑软件不适用于该目的。 ViewModel用于存储尽可能多的UI数据。 因此,在配置更改期间不需要重新加载或重新生成该数据。 另一方面,如果框架关闭了进程,则onSaveInstanceState应该存储恢复UI状态所需的最少数据量。 例如,您可以将用户的所有数据存储在ViewModel中,而仅将用户的数据库ID存储在onSaveInstanceState中。

ViewModel和上下文 (ViewModel and Context)

ViewModels should not hold a reference to Activities, Fragments, or Contexts. Furthermore, ViewModels should not include references to UI controllers like Views since this will create an indirect reference to a Context. When you rotate the screen that activity is destroyed, you have a ViewModel that holds a reference to a destroyed activity, and this is a memory leak. So, if you need to use contexts, you must use application context (AndroidViewModel subclass).

ViewModels不应包含对“活动”,“片段”或“上下文”的引用。 此外,ViewModels不应包含对UI控制器(如Views)的引用,因为这将创建对Context的间接引用。 旋转活动被破坏的屏幕时,您有一个ViewModel持有对被破坏活动的引用,这是内存泄漏。 因此,如果需要使用上下文,则必须使用应用程序上下文( AndroidViewModel子类)。

结论 (In conclusion)

As a matter of fact, ViewModel is a class that is responsible for preparing and handling the data for an Activity or a Fragment. Also, it manages the communication of the Activity and Fragment with the rest of the application like calling the business logic classes. This essay considered ViewModel concepts, and also the required steps to implement ViewModel in Android applications.

实际上,ViewModel是一个类,负责为Activity或Fragment准备和处理数据。 此外,它还管理Activity和Fragment与应用程序其余部分的通信,例如调用业务逻辑类。 本文考虑了ViewModel概念,以及在Android应用程序中实现ViewModel所需的步骤。

翻译自: https://medium.com/kayvan-kaseb/using-android-jetpack-viewmodel-2cce06983f52

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值