Android MVVM详解
Posted Mubly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android MVVM详解相关的知识,希望对你有一定的参考价值。
一、MVVM组成
(1).Model:数据层,包含数据实体和对数据实体的操作
(2).View:界面层,对应于Activity,XML,View,负责数据显示以及用户交互。
(3).ViewModel:关联层,将Model和View进行绑定,Model或者View更改时,实时刷新对方。
使用细节
1.View只做和UI相关的工作,不涉及任何业务逻辑,不涉及操作数据,不处理数据。UI和数据严格的分开
2.ViewModel只做和业务逻辑相关的工作,不涉及任何和UI相关的操作,不持有控件引用,不更新UI。
二、android MVVM持有关系与模式图
View
显而易见Activity/Fragment(XML)便是MVVM中的View,当收到ViewModel传递过来的数据时,Activity/Fragment负责将数据以你喜欢的方式显示出来。当然View还包括ViewDataBinding
ViewModel
ViewModel作为Activity/Fragment与其他组件的连接器。负责转换和聚合Model中返回的数据,使这些数据易于展示,并把这些数据改变即时通知给Actvity/Fragment。
ViewModel是具有生命周期意识的,当Activity/Fragment销毁时ViewModel的onClear方法会被回调,你可以在这里做一些清理工作。LiveData是具有生命周期意识的一个可观察的数据持有者,ViewModel中的数据有LiveData持有,并且只有当Activity/Fragment处于活动时才会通知UI数据的改变,避免无用的刷新UI。
Model
Repository及其下方就是model了。Repository负责提取和处理数据。数据来源可以是本地数据库,也可以来自网络,这些数据统一有Repository处理,一般对外隐藏数据获取方式
Binder绑定器
Android中的数据绑定技术由DataBinding和LiveData共同实现。当Activity/Fragment接收到来自ViewModel中的新数据时(由LiveData自动通知数据的改变),将这些数据通过DataBinding绑定到ViewDataBinding中,UI将会自动刷新。
三、Jetpack组件
1.databind
使用声明性格式将布局中的界面组件绑定到应用的数据源(就是相互赋值),viewModel与view进行交互的核心组件,注意对 Binding Adapter的使用官方使用
2.viewModel
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准备和管理数据的类。它还处理Activity/Fragment与应用程序其余部分的通信(例如调用业务逻辑类)。
屏幕旋转Activity 与ViewMode声明周期对比
可以看到即使是发生屏幕旋转,旋转之后拿到的ViewModel跟之前的是同一个实例,即发生屏幕旋转时,ViewModel并不会消失重建;而如果Activity是正常finish(),ViewModel则会调用onClear()销毁。
基于此我们应该了解:
- ViewModel可以在Activity配置更改中保留其状态。它保存的数据可立即供下一个Activity实例使用,无需在onSaveInstanceState()中保存数据并手动恢复。
- ViewModel比特定的Activity或Fragment实例更长。
- ViewModel允许在Fragments之间轻松共享数据(这意味着您不再需要通过活动协调操作)。
- ViewModel将保留在内存中,直到它的作用域生命周期永久消失.
- 由于ViewModel比Activity或Fragment实例更长,因此它不应直接引用其中的任何Views或保持对上下文的引用。这可能会导致内存泄漏
- 如果ViewModel需要Application上下文(例如,查找系统服务),它可以继承AndroidViewModel类并具有在构造函数中接收Application的构造函数。
3.LiveData
LiveData是一个可观察的数据存储类,它可以包含任何类型的数据,并在数据发生变化的时候通知给观察者,也就是Activity\\Fragment,让它及时更新。LiveData只会将更新通知传递给处于活跃状态的观察者(STARTED\\RESUMED)。
当Lifecycle对象的状态变为DESTROYED的时候,也就是Activity\\Fragment生命周期被销毁时,系统会立即退订
注意点:LiveData是一种可观察的数据存储器类。通俗点说就是存储数据,同时可以被观察者观察数据的变化,具有生命周期感知能力,这种感知能力可确保LiveData仅更新处于活跃生命周期状态的应用组件观察者。
因此,在其他应用场景要考虑数据丢包问题
android dataBinding详解
官方介绍地址:http://developer.android.com/intl/zh-cn/tools/data-binding/guide.html
2015 Google IO 大会带来的 Data Binding 库使得 Android 开发者可以方便的实现 MVVM 架构模式。使用DataBinding可以改善应用程序的开发,使代码更加干净优雅。何为MVVM模式,其实就是在View和Model层之间多了一层ViewModel,避免之前MVC模式中View层直接操作Model层,从而使代码结构更加清晰。有兴趣的可以看看之前转载的一篇关于关于开发模式的介绍:http://blog.csdn.net/xiangzhihong8/article/details/52671151
今天要介绍的是databining(数据绑定),对于用这个的好处和坏处我也不多说,有好处也有坏处:点击打开链接。
配置环境
默认需要将Android studio升级到1.3(估计现在大部分都满足),这是因为databinding的build.gradle需要满足最低1.3(Android Studio 已经内置了对 Android Data Binding 框架的支持)。使用的时候只需要在build.gradle添加下面的脚本:
dataBinding {
enabled = true
}
Data Binding 是一个 support 包,添加完后,你会发现我们的External Libraries中多了四个aar包:
adapters-1.1 定义了一些DataBinding的组件
baseLibrary-2.1.3 定义了一些DataBinding的annotation和回调接口
compiler-2.1.3 定义了一些用于编译DataBinding的工具类
library-1.1 定义了一些Observable基本类型
DataBinding库改变了android传统开发流程中Layout文件的编写方式,通过ViewModel,将视图和Model绑定在一起,你只需要修改Model层的值,对应的View层就会监听到自动修改自身。(其实也就是达到了页面和数据的分离)
讲了这么多理论的东西,那么到底怎么使用DataBinding呢?
首先我们需要写一个layout,不过Data Binding layout的和传统的layout的写法不一样,起始根标签是 layout,接下来一个 data 元素以及一个 view 的根元素。这个 view 元素就是你没有使用 Data Binding的layout文件的根元素。
一般在正式写代码的顺序上我们会先定义一个viewmodel类,如下:
public class UserModel {
private String firstName;
private String lastName;
public UserModel(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
}
然后在实现一个布局(技巧就在这里面):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.xzh.databinding.model.UserModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}" />
</LinearLayout>
</layout>
请注意这个layout的文件名,DataBinding会根据这个layout的文件名生成一个xxBinding类,这个类继承自ViewDataBiding;如果layout文件名是content_main.xml,则会生成一个ContentMainBinding类,根据官方解释是自动把layout文件名的下滑线去掉,然后采用驼峰式的命名规则,然后再加上Binding后缀。
com.xzh.databinding会根据xml文件的名称 Generate 一个继承自 ViewDataBinding 的类。例如,这里 xml 的文件名叫 activity_main.xml,那么生成的类就是 ActivityMainBinding。
最后需要实现通过ViewModel实现View和Model的数据绑定(常常写在Activity层,如果项目比较大的话,建议将网络请求单独分层 )。
private void getSearchData(String search) {
binding.progressBar.setVisibility(View.VISIBLE);
MovieHttpManager.searchMovies(search, new MovieHttpManager.IMovieResponse<List<Movie>>() {
@Override
public void onData(List<Movie> list) {
MovieAdapter mAdapter = new MovieAdapter(MovieActivity.this, list);
binding.recyclerView.setAdapter(mAdapter);
binding.progressBar.setVisibility(View.GONE);
}
});
}
这里用到的Adapter是RecyclerView.Adapter。不过虽然这种写法比较新颖,但是对于初学者还是不太容易接受。原理介绍请链接:
dataBinding原理大揭秘
源码:点击打开链接
以上是关于Android MVVM详解的主要内容,如果未能解决你的问题,请参考以下文章
Android中具有干净架构的mvvm和没有干净架构的mvvm有啥区别?