DataBinding双向绑定

DataBinding简介

DataBinding是由谷歌公司于2015年发布的Android数据绑定库,已更新为正式版。

DataBinding使我们远离了findViewById和各种的setValue,大大大简化了开发工作,也是的Android从官方层面上支持MVVM模式的体现。

问题来源

用过此框架的童鞋们知道,DataBinding库虽然已经实现了单向绑定,即数据的改变直接影响视图显示,但是没有实现双向绑定,即视图的改变影响数据。这离MVVM模式还差了一步。是否有解决的方案呢?答案是肯定的。
MVVM示意图

实现Data Binding双向绑定

废话说完,步入正题,我们实现原则是,尽量少写代码,尽量用原有的框架实现。(谁叫我懒呢)实现的原理便是绑定事件监听。在Data Binding中官方集成了很多实用的事件绑定,他们的声明藏在android.databinding.adapters包下以BindingAdapter为结尾的类中,下图为包中的部分截图。(全部的太长了,手懒)

BindingAdapter

举个栗子

接下来我们就以EditText为例实现数据的双向绑定。 对于EditText控件我们需要绑定一个事件监听内容的实时变化,好在Data Binding已经在android.databinding.adapters包下的TextViewBindingAdapter为我们定义好了监听,我们可以通过在布局文件中用android:afterTextChanged=function(Editable s)实现,如果把它和元素的setter函数绑定,就可以不用增加单独的监听函数。 下面是实例代码

ViewModel层

1
2
3
4
5
6
7
8
9
10
11
12
public class ViewModel extends BaseObservable {
private ObservableField<String> userName;
public ViewModel() {
userName=new ObservableField<>();
}
public String getUserName() {
return userName.get();
}
public void setUserName(Editable userName) {
this.userName.set(String.valueOf(userName));
}
}

View层-XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.xiezt.test.MainActivity">

<data>

<variable
name="viewModel"
type="com.example.databinding.ViewModel"/>
</data>

<LinearLayout
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:afterTextChanged="@{viewModel.setUserName}"
android:text="@{viewModel.userName}"/>

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onclick"
android:text="OK"/>
</LinearLayout>
</layout>

View层 Activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private ViewModel viewModel;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewModel = new ViewModel();
binding.setViewModel(viewModel);
}

public void onclick(View view) {
Toast.makeText(getApplicationContext(), viewModel.getUserName(), Toast.LENGTH_LONG).show();
}
}

效果图

效果图

总结

在官方还没有进一步完善此框架时,用现有的事件绑定来实现双向绑定算作是较为简单的解决方案。其他控件的双向绑定的解决思路,由于EditText事件的特殊性,我们不用单独写函数,但是其他控件不一定,例如CheckBox,它的绑定函数需要需要传递两个值,需要我们自己单独写。


相关链接