github simpledemo
1. DataBinding特点
- 这个库是在在2015年7月发布的Android Studio v1.3.0 版本上引入,在2016年4月Android Studio v2.0.0 上正式支持。目前为止,Data Binding 已经支持双向绑定了。
-
Data Binding 是一个support库,最低支持到Android 2.1(API Level 7+)。*
-
之前我们对布局的操作一般是通过如 findViewById()、setText(),setVisibility(),setEnabled() 或 setOnClickListener() 等,一系列的逻辑可能都会写入到activity中或者其他mode中,binding库改进了这个流程,可以在布局中写逻辑,数据的绑定操作我们都可以在xml中编写了,不需要我们对控件进行任何赋值操作,这样极大的优化了代码的耦合度和简洁程度。
2. 基本使用
- model级别的gradle加入
android {
....
dataBinding {
enabled true
}
}
- 基本的数据绑定
对需要绑定的xml顶级布局使用<layout>标签,一个xml钟只能包含一个<data>标签,我们可以在data标签中import我们的类,或者通过variable声明我们的变量。
TextView的text使用了@{String.valueOf(user.age),text接收的是一个string所以需要转换下,引用格式为@{}。通过
variable中的name,我们可以和在正常java文件中一样使用这些字段变量了,包括import进来的类也是一样的,我们可以导入任何你需要使用的类。
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.liangfeizc.databinding.model.User" />
<import type="com.liangfeizc.databinding.utils.MyStringUtils" alias="StringUtils" />
<import type="android.view.View" />
<variable name="user" type="User" />
</data>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(user.age)}" />
</layout>
代码中调用
通过DataBindingUtil的setContentView方法返回了一个ActivityBasicBinding对象,ActivityBasicBinding是通过xml自动生成的,编译器如何解决要生成类是通过<layout>这个标签来决定的。binding.setUser(user),这句代码之后(setUser是是xml中定义的variable的name自动生成出来的),数据就会自动设置到我们的view中了,不需要写入其他的设置View的逻辑了。
public class BasicActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityBasicBinding binding = DataBindingUtil.setContentView(
this, R.layout.activity_basic);
User user = new User("fei", "Liang", 27);
binding.setUser(user);
}
}
3.includes嵌套layout的绑定
有时候我们的xml中可能会存在一些includ标签,引用其他的layout,这个时候数据的绑定该如何操作。
这是layout_btn_ok的xml,定义了二个变量在Button中使用了。
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="okText"
type="String"/>
<variable
name="listener"
type="com.liangfeizc.databinding.listener.OkListener"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:onClick="@{listener.onClickOk}"
tools:text="ok"
android:text="@{okText}"/>
</LinearLayout>
</layout>
activity_main的xml,这个xml我们需要引用layout_btn_ok的布局。 main布局中我们也定义了和 btn布局中一样的变量值,如果有被引用布局而且布局中有使用变量,我们就需要在,引用布局中也声明和这个xml一样的值,进行绑定。通过bind:okText="@{okText}" bind:listener="@{listener}"这个二个bind我们就把值给传递到了btn布局中,这个布局就可以正常的使用变量了。
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.liangfeizc.databinding.model.User" />
<variable
name="user"
type="User" />
<variable
name="listener"
type="com.liangfeizc.databinding.listener.OkListener" />
<variable
name="okText"
type="String" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/layout_btn_ok"
bind:okText="@{okText}"
bind:listener="@{listener}"/>
</LinearLayout>
</layout>
代码中使用
ActivityIncludeBinding binding = DataBindingUtil.setContentView(
this, R.layout.activity_include);
binding.setListener(this);
binding.setOkText("to toast");
User user = new User("test", "Liang");
binding.setUser(user);
4.集合的使用
databinding也支持在xml中使用集合。
这里省略了<layout>标签
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="list[index]:" />
<TextView
android:text="@{list[index]}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="sparse[index]:" />
<TextView
android:text="@{sparse[index]}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="map[key]:" />
<TextView
android:text="@{map[key]}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<View
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/black" />
<TextView
android:text='map["firstName"]'
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text='@{map["firstName"]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="map[`firstName`]"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="@{map[`firstName`]}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="map[&quot;firstName&quot;]"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="@{map["firstName"]}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
只要数据更新,xml中的操作集合的逻辑就会起到作用。
CollectionsBinding binding = DataBindingUtil.setContentView(
this, R.layout.activity_collection);
String[] literals = new String[]{"liang", "fei"};
List<String> list = new ArrayList<>();
SparseArray<String> sparse = new SparseArray<>(2);
String key = "firstName";
int index = 0;
for (int i = 0; i < literals.length; i++) {
list.add(literals[i]);
sparse.put(0, literals[i]);
}
Map<String, String> map = new HashMap<>();
map.put(key, "liang");
map.put("lastName", "fei");
binding.setIndex(index);
binding.setKey(key);
binding.setList(list);
binding.setSparse(sparse);
binding.setMap(map);
5.使用资源
dataBinding中也能支持使用各种资源文件,通过@dimen/largePaddin我们使用了dimen中的一个dm属性。一些string color Image 等资源都可以通过这种方式使用。
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class="ResourceBinding">
<variable name="large" type="boolean" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:padding="@{large? (int)@dimen/largePadding : (int)@dimen/smallPadding}"
android:background="@android:color/black"
android:textColor="@android:color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</LinearLayout>
</layout>
6. BindingAdapter注解
这个注解可以动态接收到xml中使用的属性
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.liangfeizc.databinding.sample.attributesetter.AttributeSettersActivity"/>
<variable
name="activity"
type="AttributeSettersActivity"/>
<variable
name="imageUrl"
type="String"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.liangfeizc.databinding.view.NameCard
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginEnd="@dimen/largePadding"
android:layout_marginLeft="@dimen/largePadding"
android:layout_marginRight="@dimen/largePadding"
android:layout_marginStart="@dimen/largePadding"
android:gravity="center"
app:age="27"
app:firstName="@{@string/firstName}"
app:lastName="@{@string/lastName}"/>
<com.liangfeizc.avatarview.AvatarView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:error="@{@drawable/error}"
app:imageUrl="@{imageUrl}"
app:onClickListener="@{activity.avatarClickListener}"/>
</LinearLayout>
</layout>
@BindingAdapter({"imageUrl", "error"}) 中的属性就是我们需要接收的属性,必须在xml中存在而且是以app:命名空间。方法名字必须是 public staitc方式命名,方法名没要求,参数值需要和属性中使用的值对应。参数可以需要一样。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_attribute_setters);
mBinding.setActivity(this);
mBinding.setImageUrl(Randoms.nextImgUrl());
}
@BindingAdapter({"imageUrl", "error"})
public static void loadImaasdge(ImageView view, String url, Drawable error) {
Log.d(App.TAG, "load image");
Picasso.with(view.getContext()).load(url).error(error).into(view);
}
网友评论