目录
简单配置
1.app模块下的build.gradle文件的Android块中,添加:
dataBinding {
enabled = true
}
2.对生成的layout文件,使用Alt+Enter,转化为binding layout:
基本使用(单、双向绑定)
一.定义model
public class User{
private ObservableField<String> name ;
private ObservableField<Integer> age ;
private ObservableField<String> picUrl ;
private ObservableField<String> introduce ;
public User() {
}
public User(String name, int age, String picUrl, String introduce) {
this.name = new ObservableField<>(name);
this.age = new ObservableField<>(age);
this.picUrl = new ObservableField<>(picUrl);
this.introduce = new ObservableField<>(introduce);
}
... //getter setter
}
如果要实现单、双向绑定,这里的getter 和 setter是不能少的,不能少的,不然会失效。同时,写法是如下:
public ObservableField<String> getName() {
return name;
}
public void setName(ObservableField<String> name) {
this.name = name;
}
不是这种写法:
public String getName(){
return name.get();
}
public void setName(String name){
this.name.set(name);
}
或者使用下面的方法:
- 实体类继承BaseObservale类
- 在Getter上使用注解@Bindable
- 在Setter里调用方法notifyPropertyChanged
二.在xml中引入model
<data>
<variable
name="User"
type="com.xxx.model.User" />
</data>
使用如下:
<TextView
android:id="@+id/textName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{User.name}" />
<TextView
android:id="@+id/textAge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(User.age)}" />
<EditText
android:id="@+id/editIntroduce"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:hint="@string/edit_introduce_hint"
android:text="@={User.introduce}" />
注意:
- int、float等值需要转化为String类型,看源码可以知道,是调用view的seText进行赋值,这个方法的传参必须是String类型的;
- 双向绑定,只是在*@*后面加=号
三.添加监听事件
定义事件处理类,类似MVP中的P(这里定义在Activity中):
public class UserPresenter {
public void onUpdateIntroduce(User user) {
Log.e(TAG, "onUpdateIntroduce: " + user.toString());
}
}
在xml中引入:
<data>
<variable
name="User"
type="com.xxx.model.User" />
<variable
name="UserPresenter"
type="com.xxx.view.MainActivity.UserPresenter" />
</data>
使用:
<Button
android:id="@+id/btnSure"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:onClick="@{()->UserPresenter.onUpdateIntroduce(User)}"
android:text="@string/btn_sure" />
或者使用@UserPresenter::onUpdateIntroduce(User)
四.生成databinding,并给databinding赋值
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User("John", 20, "https://www.xxx.com/img/my_head.jpg", "Hello World");
binding.setUser(user);
binding.setUserPresenter(new UserPresenter());
五.使用自定义属性,BindingAdapter
定义一个处理自定义属性的类和方法:
public class ImageViewAdapter {
@BindingAdapter(value = "url", requireAll = false)
public static void setImageUrl(ImageView imageView, String url){
Glide.with(BaseApplication.getContext()).load(url).into(imageView);
}
使用:
<ImageView
android:id="@+id/imagePic"
android:layout_width="100dp"
android:layout_height="100dp"
bind:url="@{User.picUrl}" />
bind声明:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
这样就可以使用了,但是这个时候的url,如果填入值,是不会有值匹配显示的,类似这样:
可以通过在style中定义一个declare-styleable:
<declare-styleable name="ImageView">
<attr name="url"/>
</declare-styleable>
然后再看:
不用指定attr的format,否则一样不显示,但是使用app命名空间就会显示。这个设置不会影响使用,只是少了自动匹配model的属性,以及按住Ctrl跳转的功能。
缺点分析
通过上面的例子可以看到,这里存在2个问题。
- 事件触发或其他逻辑操作必须要有一个类似Presenter角色的类持有(不要直接写到model或者Activity中);
- model层不得不被改变属性类型,或者不得不加一些注解。
Demo
下一篇文章会介绍经过封装的形式,相对高级一点点