前面一段时间学习了一下Android中的DataBinding,但是只是很简单地实现了一下,DataBinding中最强大的地方还没有认真地学习过,有很多地方还不理解。这次,深入学习一下DataBinding的双向绑定和MVVM模式。

1、实现简单的使用

先回顾一下简单的使用,使用的时候需要在模块的build.gradle文件中添加这一句:

dataBinding{

enabled=true

}

添加这一句之后,gladle文件sync之后就可以开始使用。

接着我们开始搭建一个基于MVVM+DataBinding简单的开发框架。

1.1、view层

首先是新建一个全局的View的接口和一个基类的BaseActivity,具体代码如下:

//全局的接口

public interface IView {

void setViewModel(BaseVM baseVM);

}

//基类的BaseActivity

public abstract class BaseActivity extends AppCompatActivity implements IView{

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

}

}

基类的activity在具体的项目中会封装一些常用的方法,比如实现的activity的安全退出等,这里不是真实的项目,所以就没有封装那些方法。

1.2、viewmodel层

上面搭建完成view层,接着是viewmodel层。同样,需要建一个全局的基类BaseVM,BaseVM的具体代码如下:

public class BaseVM {

public String getString(int resID) {

return TestApplication.getContext().getString(resID);

}

}

这里的这个方法是用于获取资源文件里面的字符串,直接写在这里,我们需要在VM中使用的时候可以直接使用,方便。

1.3、model层

model层的话很多都是数据bean,这里我们新建一个简单的bean,这个bean只是简单的封装一些显式信息,为了可以实现自动更新,我们需要做一些处理,具体的代码如下:

public class UserBean extends BaseObservable {

private String userCard;

private String userName;

private String userAddres;

private String userEmail;

public UserBean() {

}

public UserBean(String userCard, String userName, String userAddres, String userEmail) {

this.userCard = userCard;

this.userName = userName;

this.userAddres = userAddres;

this.userEmail = userEmail;

}

@Bindable

public String getUserCard() {

return userCard;

}

public void setUserCard(String userCard) {

this.userCard = userCard;

notifyPropertyChanged(cn.amos.BR.userCard);

}

@Bindable

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

notifyPropertyChanged(cn.amos.BR.userName);

}

@Bindable

public String getUserAddres() {

return userAddres;

}

public void setUserAddres(String userAddres) {

this.userAddres = userAddres;

notifyPropertyChanged(cn.amos.BR.userAddres);

}

@Bindable

public String getUserEmail() {

return userEmail;

}

public void setUserEmail(String userEmail) {

this.userEmail = userEmail;

notifyPropertyChanged(cn.amos.BR.userEmail);

}

@Override

public String toString() {

return "UserBean{" +

"userCard=" + userCard +

", userName='" + userName + '\'' +

", userAddres='" + userAddres + '\'' +

", userEmail='" + userEmail + '\'' +

'}';

}

}

这里继承了BaseObservable这个类,以及后面在Get方法上面添加@Bindable注解为了实现自动更新,也是需要在set方法中添加notifyPropertyChanged(cn.amos.BR.userEmail);这一句代码,这里是提醒更新数据。需要注意的是BR这个类,比较容易弄乱。

还做一个封装就是DataBindingUtils,看一下具体的代码:

public class DataBindingUtils {

private static ArrayMap> commonMap = new ArrayMap<>();

public static void addCallBack(BaseActivity baseActivity,

Observable observable, Observable.OnPropertyChangedCallback callback) {

ArrayMap callbackArrayMap = commonMap.get(baseActivity);

if (callbackArrayMap == null) {

callbackArrayMap = new ArrayMap<>();

commonMap.put(baseActivity, callbackArrayMap);

}

observable.addOnPropertyChangedCallback(callback);

callbackArrayMap.put(observable, callback);

}

public static void removeCallBack(BaseActivity activity) {

ArrayMap callbackArrayMap = commonMap.get(activity);

if (callbackArrayMap != null) {

for (Observable observable : callbackArrayMap.keySet()) {

observable.removeOnPropertyChangedCallback(callbackArrayMap.get(observable));

}

}

}

}

这里封装了两个方法,第一个是添加回调,另外一个就是移除回调,没有什么很复杂的东西,需要解析一下的就是:Observable.OnPropertyChangedCallback,这是一个当observable中的属性发生改变时由Observable调用的回调接口,需要实现的就是一个onPropertyChanged(Observable observable, int i)这个方法,两个属性,第一个是observable是正在改变的observable,另外一个是需要用BR标识,并且get方法上面需要添加@Bindable注解。需要了解这个API的,可以点击这里

到这里,基本就可以完成了框架的简易搭建,当然,这里只是非常简单的,在实际项目中还需要其他的东西,这里只是一个简单的Demo,所以就简单一点,接下来我们开始实现具体的业务。

2、实现按钮的点击

首先我们先实现一个简单的按钮点击,跳转另外界面的一个需求。

首先是新建一个activity和对应的XML文件,具体的代码分别是:

public class MainActivity extends BaseActivity {

private MainActivityVM mActivityVM;

private ActivityMainBinding mDataBinding;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mActivityVM = new MainActivityVM();

setViewModel(mActivityVM);

addCallBack();

}

private void addCallBack() {

DataBindingUtils.addCallBack(this, mActivityVM.goToSimple, new Observable.OnPropertyChangedCallback() {

@Override

public void onPropertyChanged(Observable observable, int i) {

goToBase();

}

});

}

private void goToBase() {

startActivity(new Intent(MainActivity.this, SimpleActivity.class));

}

@Override

public void setViewModel(BaseVM baseVM) {

this.mActivityVM = (MainActivityVM) baseVM;

mDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

mDataBinding.setMainActivityVM(mActivityVM);

}

}

这里的activity需要继承BaseActivity,然后需要实现setViewModel(BaseVM baseVM)这个方法,这个是在IView这个接口中的,每个继承于BaseActivity的都需要实现这个方法,这个方法就是设置一个VM的。

然后是XML的代码:

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools">

name="mainActivityVM"

type="MainActivityVM"/>

android:id="@+id/activity_main"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context="cn.amos.view.MainActivity">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:onClick="@{mainActivityVM.goToNext}"

android:text="简单实现绑定数据"/>

这里需要一个MainActivityVM,这个类的代码是:

public class MainActivityVM extends BaseVM {

public ObservableInt goToSimple = new ObservableInt();

public void goToNext(View view) {

goToSimple.notifyChange();

}

}

这里就一个方法,这个方法GoToNext,这个是button的点击事件,注意需要传入一个View的参数。这里调用了 goToSimple.notifyChange();这个方法,会在MainActivity中实现回调,我们在MainActivity中有一个addCallBack的方法中添加了这个回调的监听。

public ObservableInt goToSimple = new ObservableInt();

这个也是实现数据更新的,不过比实现BaseObservable这个类更加细。

这样就可以实现点击跳转了。

3、实现一些简单信息更新

新建一个SimpleActivity、对应的XML文件和SImpleActivityVM,具体的代码是:

首先是SimpleActivity的代码:

public class SimpleActivity extends BaseActivity {

private static final String TAG = "SimpleActivity";

private SimpleActivityVM mSimpleActivityVM;

private ActivitySimpleBinding mSimpleBinding;

private Toolbar mTbSimple;

private UserBean mUserBean = new UserBean();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mSimpleActivityVM = new SimpleActivityVM();

setViewModel(mSimpleActivityVM);

addCallBack();

initUi();

}

private void initUi() {

mTbSimple = mSimpleBinding.tbSimple;

setSupportActionBar(mTbSimple);

mTbSimple.setNavigationOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

finish();

}

});

}

private void addCallBack() {

DataBindingUtils.addCallBack(this, mSimpleActivityVM.mUserBeanObservableField, new Observable.OnPropertyChangedCallback() {

@Override

public void onPropertyChanged(Observable observable, int i) {

mUserBean.setUserAddres(mSimpleActivityVM.userAddres.get());

mUserBean.setUserCard(mSimpleActivityVM.userCard.get());

mUserBean.setUserEmail(mSimpleActivityVM.userEmail.get());

mUserBean.setUserName(mSimpleActivityVM.userName.get());

}

});

}

@Override

public void setViewModel(BaseVM baseVM) {

mSimpleBinding = DataBindingUtil.setContentView(this, R.layout.activity_simple);

mSimpleActivityVM = (SimpleActivityVM) baseVM;

mSimpleBinding.setSimpleActivityVM(mSimpleActivityVM);

mUserBean.setUserAddres("shanghai");

mUserBean.setUserName("Amos");

mUserBean.setUserEmail("123@163.com");

mUserBean.setUserCard("819365189");

mSimpleBinding.setUserBean(mUserBean);

}

}

这个也是要继承BaseActivity,也要实现setViewModel这个方法,在这里我们做一些数据的初始化以及设置一些Variable。

接着是XML文件的代码:

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools">

name="simpleActivityVM"

type="cn.amos.vm.SimpleActivityVM"/>

name="userBean"

type="cn.amos.model.UserBean"/>

android:layout_width="match_parent"

android:layout_height="match_parent"

android:fitsSystemWindows="true"

tools:context="cn.amos.view.SimpleActivity">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:theme="@style/AppTheme.AppBarOverlay">

android:id="@+id/tb_simple"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

android:background="?attr/colorPrimary"

app:navigationIcon="?attr/homeAsUpIndicator"

app:popupTheme="@style/AppTheme.PopupOverlay"

app:title="简单使用"/>

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginTop="?attr/actionBarSize"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="10dp"

android:text="原来的信息"

android:textSize="16sp"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="user Card:"

android:textSize="18sp"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@{userBean.userCard}"

android:textSize="18sp"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="userName:"

android:textSize="18sp"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@{userBean.userName}"

android:textSize="18sp"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="userAddre:"

android:textSize="18sp"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@{userBean.userAddres}"

android:textSize="18sp"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="userEmail:"

android:textSize="18sp"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@{userBean.userEmail}"

android:textSize="18sp"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="15dp"

android:layout_marginRight="15dp"

android:layout_marginTop="20dp">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:hint="请输入卡号"

android:text="@={simpleActivityVM.userCard}"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="15dp"

android:layout_marginRight="15dp"

android:layout_marginTop="20dp">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:hint="请输入用户名"

android:text="@={simpleActivityVM.userName}"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="15dp"

android:layout_marginRight="15dp"

android:layout_marginTop="20dp">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:hint="请输入用户住址"

android:text="@={simpleActivityVM.userAddres}"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="15dp"

android:layout_marginRight="15dp"

android:layout_marginTop="20dp">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:hint="请输入邮箱"

android:text="@={simpleActivityVM.userEmail}"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:onClick="@{simpleActivityVM.updateData}"

android:text="更新信息"/>

这里实现的就是,上面是几个textView,显示一些最开始的信息,然后后面是几个EditText和一个Button,在EditText输入信息,点击Button可以更新上面TextView显示的信息。这里需要注意的是@={simpleActivityVM.userEmail},这里,不要忘记那个等号,否则会获取不到EditText中的信息。

最后是SimpleActivityVM的代码:

public class SimpleActivityVM extends BaseVM {

private static final String TAG = "SimpleActivityVM";

public ObservableField mUserBeanObservableField = new ObservableField<>();

public ObservableField userCard = new ObservableField<>("");

public ObservableField userAddres = new ObservableField<>("");

public ObservableField userName = new ObservableField<>("");

public ObservableField userEmail = new ObservableField<>("");

public SimpleActivityVM() {

}

public void updateData(View view) {

mUserBeanObservableField.notifyChange();

}

}

这里面的ObservableField是需要更新的属性,最好实例化。当我们点击Button的时候,会实现回调,然后在SimpleActivity中重新设置TextView里面的数据,实现更新。

这样就可以完成我们一开始的需求,初始化数据,然后在EditText中输入,点击按钮实现更新。这里是第一部分简单的DataBinding的使用,下一篇中我们会在RecyclerView、ViewPager等中使用DataBinding。还有做一些简单的RecyclerView的封装,比如实现下拉刷新和上拉加载更多等。

android实现双向绑定,Android使用DataBinding实现双向绑定(一)相关推荐

  1. DataBinding的双向绑定实现原理

    " 悄悄咪咪告诉你,DataBinding是怎么实现双向绑定的" 在讲DataBinding之前,有必要讲讲ViewBinding 1.ViewBinding 1) 配置 要使用V ...

  2. Android MVVM封装,MVVM: 这是一个android MVVM 框架,基于谷歌dataBinding技术实现

    MVVM 这是一个android MVVM 框架,基于谷歌dataBinding技术实现.dataBinding 实现的 V 和 VM的关联:使用IOC架构实现了 M 和 V的关联. 框架具有以下功能 ...

  3. android mvvm官方文档,MVVM: 这是一个android MVVM 框架,基于谷歌dataBinding技术实现

    MVVM 这是一个android MVVM 框架,基于谷歌dataBinding技术实现.dataBinding 实现的 V 和 VM的关联:使用IOC架构实现了 M 和 V的关联. 框架具有以下功能 ...

  4. android+捕获google账户+cancel按钮,MVVM: 这是一个android MVVM 框架,基于谷歌dataBinding技术实现...

    MVVM 这是一个android MVVM 框架,基于谷歌dataBinding技术实现.dataBinding 实现的 V 和 VM的关联:使用IOC架构实现了 M 和 V的关联. 框架具有以下功能 ...

  5. Android MVVM架构设计模式,从DataBinding开始

    MVVM在android端已经出了很久了,但是还是比较少使用到,现在写Android架构设计的时候比较多使用的是MVP,以前在用Angularjs和Vue接触过双向数据绑定的使用和思想,所以看到MVV ...

  6. 【Android】17.2 Activity与Local Service的绑定

    分类:C#.Android.VS2015: 创建日期:2016-03-03 一.简介 如果服务是你的应用程序所私有的,即服务(Service)与客户端(Activity)都在同一个项目中(大部分应用程 ...

  7. android ListView布局之二(是用simpleAdapter绑定数据)

    main.xml主布局文件,代码 <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...

  8. android多个activity绑定一个service,8.1.2 绑定Activity和Service

    8.1.2  绑定Activity和Service 本节的例子代码所在的工程目录是src\ch08\ch08_serviceactivity 如果使用8.1.1节介绍的方法启动服务,并且未调用stop ...

  9. Https双向认证Android客户端配置

    Https双向认证啊  做了两遍,第一遍懵懂状态处于 好不容易做好了,换服务器,一下子懵了,使出浑身解数又找了一遍,这下终于好了  快哭啦,必须滴要记录一下,以免以后遇到继续懵,这里用retrofit ...

最新文章

  1. 3D点云补全算法汇总及最新进展
  2. Tensorflow学习笔记——word2vec
  3. led流水灯——51单片机程序
  4. C语言实现lu分解lu decompose算法(附完整源码)
  5. JavaScript图片库
  6. 智能+大数据 在云+互联时代下创造的精准营销
  7. jmeter安装配置教程
  8. java基础学习1-java实验输出希腊字母表
  9. office产品密钥如何找回
  10. 熊猫的python小课怎么样_02_Python简单爬虫(熊猫直播LOL的up主,谁最强!)
  11. @linux下tar解压失败a lone zero解决方法
  12. 台式关掉计算机不断网,笔记本电脑在关掉屏幕后不断网设置方法
  13. android调用相机分辨率,Android菜鸟笔记-获取摄像头像素值
  14. java jsf 入门_JSF入门、简单示例
  15. 201771010137赵栋《第八周学习总结》
  16. Linux中select IO复用机制
  17. 线性回归分析学习笔记第一篇:一元线性回归
  18. 各互联网大厂工程师薪资新鲜出炉,速来围观!
  19. 转行互联网运营是个坑
  20. Java、五边形的面积

热门文章

  1. 解决“Pip - Fatal error in launcher: Unable to create process using... ”
  2. c++ 读取写入txt
  3. pandas去掉html标签,用Pandas清理HTML表
  4. C语言之运算符优先级(四十二)
  5. PulseAudio多线程通信:pthread_cond_broadcast/pthread_cond_signal/pthread_cond_wait(九)
  6. Android NuPlayer播放框架
  7. 瑞芯微RK3128-微信Airkiss2.0配网功能调试及实现
  8. Android Multimedia框架总结(二十四)MediaMuxer实现手机屏幕录制成gif图
  9. Android内核开发:系统分区与镜像文件的烧写
  10. 判断显卡好坏的步骤、新买显卡装机后不亮解决