Android MVVM-编程思想2(入门实战MVVM,DataBinding,ViewModel,LiveData)
Posted 0 and 1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android MVVM-编程思想2(入门实战MVVM,DataBinding,ViewModel,LiveData)相关的知识,希望对你有一定的参考价值。
前言
通过一个小案例,帮助大家了解MVVM。最终实现一个MVVM通用框架。代码:github。(如有错误之处,请在评论区指出,谢谢。如果感觉写的不错,请点赞,关注,谢谢。)
上一个小节,只是理论介绍了MVVM,DataBinding,ViewModel,LiveData,这一小节,讲解一下他们的使用方式。如果已经对这些基础知识很了解,可以直接看下一节。
目录:
Android MVVM-编程思想1(入门介绍MVVM,DataBinding,ViewModel,LiveData)
Android MVVM-编程思想2(入门实战MVVM,DataBinding,ViewModel,LiveData)
Android MVVM-编程思想3(封装基类BaseMvvmActivity,BaseMvvmFragment)
DataBinding 使用
首先开启app模块的gradle配置文件android 节点下开启
dataBinding
enabled true
(1)最简单的使用JDK定义好的类型
xml直接使用
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="title"
type="String" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="@=title"
android:textColor="#ffffff"
android:textSize="18sp" />
</LinearLayout>
</layout>
UserActivity 中使用,DataBindingUtil.setContentView(this, R.layout.activity_user),AndroidStudio 构建之后会自动根据XML中的配置生成绑定关系。并返回管理类ActivityUserBinding
ActivityUserBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_user);
binding.setTitle("DataBinding绑定演示");
(2)如何使用自定义的类?
定义一个类User
普通的类,跟JDK内部的类一样,只是残疾版的绑定,什么意思? Model中的数据可以显示到View上。Model 的数据变动不会实时变化到View上。如何实现数据驱动,如何实现双向绑定?,继续看,后面会讲
User类
public class User
private String name;
private String sex;
private int age;
public User(String name, String sex, int age)
this.name = name;
this.sex = sex;
this.age = age;
public String getName()
return name;
public void setName(String name)
this.name = name;
@Bindable
public String getSex()
return sex;
public void setSex(String sex)
this.sex = sex;
public int getAge()
return age;
public void setAge(int age)
this.age = age;
XML中使用
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="title"
type="String" />
<variable
name="user"
type="chongchong.wei.mvvm_aac.base.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="@=title"
android:textColor="#ffffff"
android:textSize="18sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
android:text='@"名称:"+user.name'
android:textSize="18sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
android:text="@user.name"
android:textSize="18sp" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@=user.name" />
<TextView
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
android:text='@""+user.age'
android:textSize="18sp" />
<Button
android:id="@+id/mButton"
android:layout_width="100dp"
android:layout_height="40dp"
android:text="模拟请求网络" />
</LinearLayout>
</layout>
UserActivity类
public class UserActivity extends AppCompatActivity
ActivityUserBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
binding = DataBindingUtil.setContentView(this, R.layout.activity_user);
binding.setTitle("DataBinding绑定演示");
binding.setUser(new User("小明", "男", 16));
binding.mButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
requestHttp();
);
/**
* 模拟请求网络刷新数据
*/
private void requestHttp()
binding.getUser().setName("改变Name");//User没有继承BaseObservable ,View不会变化
(3)实现User数据变化,View自动更改,加上注解@Bindable,set方法手动更新notifyPropertyChanged
实现数据变化自动驱动 UI 刷新的方式有三种:BaseObservable、ObservableField、ObservableCollection
BaseObservable 提供了 notifyChange() 和 notifyPropertyChanged() 两个方法,前者会刷新所有的值域,后者则只更新对应 BR 的 flag,该 BR 的生成通过注释 @Bindable 生成,可以通过 BR notify 特定属性关联的视图
下面学习一下第一种方式:
User类
public class User extends BaseObservable
@Bindable
private String name;
@Bindable
private String sex;
@Bindable
private int age;
public User(String name, String sex, int age)
this.name = name;
this.sex = sex;
this.age = age;
public String getName()
return name;
public void setName(String name)
this.name = name;
notifyPropertyChanged(chongchong.wei.mvvm_aac.BR.name);
public String getSex()
return sex;
public void setSex(String sex)
this.sex = sex;
notifyPropertyChanged(chongchong.wei.mvvm_aac.BR.sex);
public int getAge()
return age;
public void setAge(int age)
this.age = age;
notifyPropertyChanged(chongchong.wei.mvvm_aac.BR.age);
双向数据绑定如何实现?
双向绑定的意思即为当数据改变时同时使视图刷新,而视图改变时也可以同时改变数据
需求:界面上有两个控件,EditText 用于获取用户输入,TextView 用于把用户输入展示出来,绑定变量的方式比单向绑定多了一个等号:@=user.name
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@=user.name" />
这里只是简单介绍DataBinding 的作用和使用方式。还有很多其他场景的使用方式,大家去官网自己查看吧。本系列的目的是搭建MVVM框架,所以就不在这上面讲解过多了。
ViewModel使用
ViewModel 其实就是MVVM中的VM 层 ,一般和LiveData 一起使用,根据官方介绍,VeiwModel是具有生命周期感知的。验证一下
UserVM
public class UserVM extends ViewModel
@Override
protected void onCleared()
super.onCleared();
Log.i("weicc_mvvm_", "onCleared");
UserActivity中使用
public class UserActivity extends AppCompatActivity
ActivityUserBinding binding;
UserVM userVM;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
binding = DataBindingUtil.setContentView(this, R.layout.activity_user);
binding.setTitle("DataBinding绑定演示");
userVM = ViewModelProviders.of(this).get(UserVM.class);
binding.setUserVM(userVM);
Log.i("weicc_mvvm_", "onCreate_hashcode:" + ViewModelProviders.of(this).get(UserVM.class).hashCode());
@Override
protected void onStart()
super.onStart();
Log.i("weicc_mvvm_", "onStart_hashcode:" + ViewModelProviders.of(this).get(UserVM.class).hashCode());
@Override
protected void onResume()
super.onResume();
Log.i("weicc_mvvm_", "onResume_hashcode:" + ViewModelProviders.of(this).get(UserVM.class).hashCode());
@Override
protected void onPause()
super.onPause();
Log.i("weicc_mvvm_", "onPause_hashcode:" + ViewModelProviders.of(this).get(UserVM.class).hashCode());
@Override
protected void onStop()
super.onStop();
Log.i("weicc_mvvm_", "onStop_hashcode:" + ViewModelProviders.of(this).get(UserVM.class).hashCode());
@Override
protected void onDestroy()
super.onDestroy();
Log.i("weicc_mvvm_", "onDestroy_hashcode:" + ViewModelProviders.of(this).get(UserVM.class).hashCode());
@Override
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
Log.i("weicc_mvvm_", "onConfigurationChanged_hashcode:" + ViewModelProviders.of(this).get(UserVM.class).hashCode());
启动运行,然后旋转屏幕–》点击back销毁。可以看出旋转屏幕不会重建ViewModel。
打印:
2019-12-20 15:59:43.502 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onCreate_hashcode:86643892
2019-12-20 15:59:43.503 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onStart_hashcode:86643892
2019-12-20 15:59:43.506 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onResume_hashcode:86643892
2019-12-20 15:59:49.704 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onConfigurationChanged_hashcode:86643892
2019-12-20 15:59:49.707 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onPause_hashcode:86643892
2019-12-20 15:59:49.718 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onStop_hashcode:86643892
2019-12-20 15:59:49.719 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onDestroy_hashcode:86643892
2019-12-20 15:59:49.764 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onCreate_hashcode:86643892
2019-12-20 15:59:49.766 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onStart_hashcode:86643892
2019-12-20 15:59:49.771 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onResume_hashcode:86643892
2019-12-20 15:59:53.086 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onPause_hashcode:86643892
2019-12-20 15:59:53.299 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onStop_hashcode:86643892
2019-12-20 15:59:53.302 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onCleared
2019-12-20 15:59:53.302 11594-11594/chongchong.wei.mvvm_aac I/weicc_mvvm_: onDestroy_hashcode:231874846
LiveData 使用
UserActivity代码
public class UserActivity extends AppCompatActivity
ActivityUserBinding binding;
MutableLiveData<User> mutableLiveData;
User user;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
Log.i("weicc_mvvm_", "onCreate");
setContentView(R.layout.activity_user);
binding = DataBindingUtil.setContentView(this, R.layout.activity_user);
binding.setTitle("DataBinding绑定演示");
user = new User();
user.setName("小明");
user.setAge(12);
user.setSex("男");
mutableLiveData = new MutableLiveData();
mutableLiveData.setValue(user);
mutableLiveData.observe(this, new Observer<User>()
@Override
public void onChanged(User user)
binding.setUser(user);//user没有继承BaseObservable 需要手动刷新数据到界面
Log.i("weicc_mvvm_", "监听user改变:" + user.toString());
);
binding.mButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
requestHttp();
);
/**
* 模拟请求网络刷新数据
*/
private void requestHttp()
Log.i("weicc_mvvm_", "点击button的时候改变name");
user.setName("改变name");
mutableLiveData.postValue(user);
@Override
protected void onStop()
super.onStop();
Log.i("weicc_mvvm_", "onStop的时候改变name");
user.setName("改变name");
mutableLiveData.postValue(user);
日志分析:LiveData onStop的数据改变不会推送,所以并不会监听到,正如LiveData官方说明的一样,是具有生命周期感知的观察者。
优势:1,当Activity不在屏幕上时(不可见),LiveData不会出发没必要的界面更新;2,当Activity被销毁时,LiveData将自动清空与Observer的连接
2019-12-20 16:46:42.312 22352-22352/chongchong.wei.mvvm_aac IAndroid MVVM-编程思想1(入门介绍MVVM,DataBinding,ViewModel,LiveData)
Android MVVM-编程思想1(入门介绍MVVM,DataBinding,ViewModel,LiveData)
《Android构建MVVM》系列 之 MVVM架构快速入门
Android MVVM-编程思想3(封装基类BaseMvvmActivity,BaseMvvmFragment)