什么是MVVM
- MVVM 是“Model-view-viewModel”的缩写
- model 数据实体
- view 对应于activity和xml布局 负责界面展示和与用户交互
- viewModel 负责view和Model之间的交互 负责处理业务逻辑 - 详细解释
-ViewModel只做和业务逻辑和业务数据相关的事,不做任何和UI相关的事情,ViewModel 层不会持有任何控件的引用,更不会在ViewModel中通过UI控件的引用去做更新UI的事情。ViewModel就是专注于业务的逻辑处理,做的事情也都只是对数据的操作(这些数据绑定在相应的控件上会自动去更改UI
- View层做的就是和UI相关的工作,我们只在XML、Activity和Fragment写View层的代码,View层不做和业务相关的事,也就是我们在Activity不写业务逻辑和业务数据相关的代码,更新UI通过数据绑定实现,尽量在ViewModel里面做(更新绑定的数据源即可),Activity要做的事就是初始化一些控件(如控件的颜色,添加RecyclerView的分割线),View层可以提供更新UI的接口(但是我们更倾向所有的UI元素都是通过数据来驱动更改UI),View层可以处理事件(但是我们更希望UI事件通过Command来绑定)。简单地说:View层不做任何业务逻辑、不涉及操作数据、不处理数据,UI和数据严格的分开。
- Model层最大的特点是被赋予了数据获取的职责,与我们平常Model层只定义实体对象的行为截然不同。实例中,数据的获取、存储、数据状态变化都是Model层的任务。Model包括实体模型(Bean)、Retrofit的Service ,获取网络数据接口,本地存储(增删改查)接口,数据变化监听等。Model提供数据获取接口供ViewModel调用,经数据转换和操作并最终映射绑定到View层某个UI元素的属性上。 -
MVVM 模式流程示意图
mvvm示意图.png
MVVM的一些特点
- 双向数据绑定 在双向数据绑定模式中数据流是双向的,当业务上的数据发生改变之后,ui上的数据得到实时更新。当用户通过交互改变了数据的时候,数据的改变也能够自动更新到业务代码的数据中去。 在Android中数据绑定用的是DataDinding,谷歌官网推出的实现数据和ui绑定的框架。
DataBinding的基本使用
配置环境
- 在build.gradle(app)中 配置 代码如下
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
dataBinding {
enabled = true
}
}
创建Java实体类(TODO )
DataBinding下的布局文件(TODO这个是重头戏 之后着重解释)
- <layout> 作为整个布局的根节点。在编译之后会生成一个Binding类。命名规则是:单词首字母大写,移除下划线,并在最后添加上Binding。(如下面生成的类就是ActivityMainBinding)
- 在布局中通过<variable>节点引入变量。变量名字自定。<type>标签写的是这个变量的具体类型。变量的引入是通过在activity中或者其他地方由布局文件生成的binding文件的set方法进行设置。(如果变量名字是“user”,在设置这个变量的时候,应该是(ActivityMainBinding binding.setUser(new User()))
- 示例代码如下
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="user"
type="mvvm.wangjing.com.mvvm.User.User" />
</data>
<RelativeLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="mvvm.wangjing.com.mvvm.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:onClick="@{user.onItemClick}"
android:text="@{`My name is `+ user.name+` I'm `+user.age+` years old `}" />
</RelativeLayout>
</layout>
在activity中 (代码入下) 引入布局
- 用下面的setContentView() 代替activity中原本的setContentView()
ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User("Looperjing", "20");
viewDataBinding.setUser(user);
双向绑定的布局文件
-
上面的实体类实现的是单向绑定 如果要实现双向绑定就要修改实体类这里有多重写法(TODO总结每种写法)
-
这里要用到谷歌提供的几个类
- ObservableField<> 定义泛型类,还有ObservableInt等基本数据类型的。
- 作用是当实体类的数据发生改变的时候自动通知view刷新。通过变量的set()方法来设置值。通过get()方式来获取值。想改变一个字段,需要该字段的get方法添加上@Bindable注解,然后给该字段的set方法加上 notifyPropertyChanged([mvvm.wangjing.com.mvvm.BR.name] -
例子代码如下
public class User extends BaseObservable {
public ObservableField<String> name = new ObservableField<>();
public ObservableField<String> age = new ObservableField<>();
public User(String pName, String pAge) {
name.set(pName);
age.set(pAge);
}
@Bindable
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
notifyPropertyChanged(mvvm.wangjing.com.mvvm.BR.name);
}
@Bindable
public String getAge() {
return age.get();
}
public void setAge(String age) {
this.age.set(age);
}
public void onItemClick(View pView) {
Toast.makeText(pView.getContext(), name.get(), Toast.LENGTH_SHORT).show();
setName("June");
}
}
Android中viewModel的使用
- 这里只介绍viewModel的简单使用 结合上面的数据绑定 在布局文件中引入viewModel对象,就是mvvm模式
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<User>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
- activity或者Fragment中的操作
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
网友评论