(一)
关于DataBinding
Google推出DataBinding有一段时间,但是目前来看没有几个人用(尴尬),当然Google推出很多东西都没用户(哈哈),不过作为程序猿
学习这个东西还是很有必要的,毕竟技术的革新都是在一点点试错中发展壮大。此系列参考官方文档。
说明:
支持:Android 2.1 (API level 7+)
要求:Gradle插件至少1.5.0-alpha1或更高,Android Studio 1.3+
构建环境
使用之前要先从Support respository下载支持包,不过现在基本上都有的,没有support还怎么玩。
让后在app模块的build.gradle中添加如下:
android {
....
dataBinding {
enabled = true
}
}注意:如果使用了library,而这个库使用了databinding,主模块也要配置。
布局文件
databinding的布局文件是区别于传统的layout文件,跟节点是以layout开头的,e.g.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"/>
</LinearLayout>
</layout>data节点中定义变量名称,type是变量的类型(全名:包名+类名)。
而使用这个变量类似:
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"/>Data Object
上面已经写好了布局文件,已经定义了user变量,下面我们就定义一个User类,
public class User {
// public final
public final String firstName;
public final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}这样写的实体通常是不会变化的,就跟我们平日写的JavaBean一样,但是字段必须是public和final的,还有另一种写法
public class User {
// private final 但是有getter
private final String firstName;
private final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
}绑定数据
默认定义好了layout就会生成一个以“Binding”结尾同名的丙丁对象,让后通过DataBindingUtil来将layout和Activity绑定。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User("Test", "User");
binding.setUser(user);
}- 将layout和Activity绑定
- 创建一个实体
- 将实体和布局关联起来
运行
上面简单几步,创建了一个DataBinding App现在运行起来,看看效果。
事件处理
上面只是一个简单的示例,毕竟没有人写一个只做展示而没有交互的应用,有交互必然有事件处理。DataBinding同样可以处理这些。
- 方法引用
- 监听绑定
方法引用
- 定义一个类
public class MyHandlers { public void onClickFriend(View view) { Toast.makeText(view.getContext(), "Hello World", Toast.LENGTH_SHORT).show(); } } - 修改布局文件
data节点申明变量,和类型<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="handlers" type="com.example.Handlers"/> <variable name="user" type="com.example.User"/> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.firstName}" android:onClick="@{handlers::onClickFriend}"/> </LinearLayout> </layout>
andorid:onClick中调用函数, - 赋值
这样我们的时间就绑定好了,我们运行点击,就会弹出Toast。@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); User user = new User("Test", "User"); binding.setUser(user); binding.setHandlers(new MyHandlers()); // 给变量赋值 }
说明:如果没有赋值,不会报错,也不会弹出Toast,相当于没有绑定事件。
监听绑定
这种方式只有在Gradle插件version 2.0+上才能使用。
- 定义监听类
Task表示回调参数public class Presenter { public void onSaveClick(Task task){} } - 修改layout文件
android:onClick="@{() -> presenter.onSaveClick(task)}" /> 使用lambda表达试,也可以使用下面方式<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="task" type="com.android.example.Task" /> <variable name="presenter" type="com.android.example.Presenter" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{() -> presenter.onSaveClick(task)}" /> </LinearLayout> </layout>
android:onClick="@{(view) -> presenter.onSaveClick(task)}"
两种方式各有特点,根据自己需要来选择。
(二)
上节我们讲了基本使用,这节我们继续讲讲已谢基本用法
说明:前期文章参考官方文档,因为基础知识官方写的很清楚。
导包
基本定义
上节我们使用了一下基础导包,定义一个变量,如:
<variable
name="user"
type="com.lowett.databinding.User"/>这样写有个问题,当有多个同样类型的变量时候,就显得比较麻烦了,这里DataBinding库提供了另一中方式
可以先导包,然后在定义变量,
<data>
<import type="android.view.View"/>
<!--导入User-->
<import type="com.lowett.databinding.User"/>
<!--定义变量-->
<variable
name="user"
type="User"
/>
<variable
name="listner"
type="com.lowett.databinding.HandleClick"/>
</data>定义别名
如果类冲突,我们还可以定义别名。
<data>
<import type="android.view.View"/>
<!--导入User 并定义别名-->
<import type="com.lowett.databinding.User" alias="MyUser"/>
<!--定义变量-->
<variable
name="user"
type="MyUser"
/>
<variable
name="listner"
type="com.lowett.databinding.HandleClick"/>
</data>范型定义
在Java中我们可以定义范型,在layout同样可以,但是其中的括号需要特俗定义否则会报错。
<data>
<import type="java.util.List"/>
<import type="android.view.View"/>
<!--导入User 并定义别名-->
<import type="com.lowett.databinding.User" alias="MyUser"/>
<!--定义变量-->
<variable
name="user"
type="MyUser"
/>
<!--定义范型, 如果显示红色没关系可以编译成功-->
<variable
name="users"
type="List<MyUser>"/>
<variable
name="listner"
type="com.lowett.databinding.HandleClick"/>
</data>静态方法
导入类型的时候我们也可导入工具类等的静态方法。
<data>
<import type="com.lowett.databinding.utils.Utils"/>
</data>使用:
<TextView
android:layout_width="wrap_content"
android:text="@{Utils.test()}"
android:layout_height="wrap_content"/>默认导入的变量
在layout中有默认导入几种常用的类型,比如String,Context等,这些何以直接使用,如果显式指定了类型将会修改掉默认的。
在layout中还有一个context变量可以直接使用。
如我们获取屏幕尺寸:
注意:需要讲int转换为String。
这里并没有定义context,以及导入String包,默认有。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.lowett.databinding.utils.Utils"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:text="@{String.valueOf(Utils.getScreenWidth(context))}"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>Utils.java:
public class Utils {
public static String test() {
return "Test";
}
public static int getScreenWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
}自定义类名
默认的我们生成的binding类名是以布局文件的名字接一个Binding为后缀,我们也可以修改这个名字。
如:
<data class="MyDataClass">
</data>在布局文件中data节点天街class属性并定义名字,生成MyDataClass绑定对象。位于跟包名下。
如果向指定包名,那么写全名即可。
<data class="com.lowett.databinding.utils.MyDataClass">
</data>这样将会在com.lowett.databinding.utils下面生成绑定类。
参考官方文档。
未完待续