你是否看过别人的layout并想:这个值在哪里设置和获取.或者,你觉得不需要findViewById了是很好的一个开始,但仍然存在很多样板代码.Android Data Binding让这个变得简单.
使用ViewHolder模式<a id="orgheadline3"></a>
假设我们需要在应用中显示用户信息. 在前面,我展示了使用Android Studio
通过如下的layout文件生成一个"View Holder"类:
user_info.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/userImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/userFirstName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/userLastName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
然后给View设置数据:
private void setUser(User user, ViewGroup root) {
UserInfoBinding binding =
UserInfoBinding.inflate(getLayoutInflater(), root, true);
binding.userFirstName.setText(user.firstName);
binding.userLastName.setText(user.lastName);
binding.userImage.setImageBitmap(user.image);
}
虽然这看上去要比findViewById好, 但仍然存在很多的样板代码!
可以通过在layout文件中使用data binding表达式来消除这些样板代码,
实现自动赋值.
给变量赋值<a id="orgheadline4"></a>
首先, 增加一个binding表达式需要的 data 标签以及一个相关变量.
然后, 对于layout中需要赋值的属性, 使用binding表达式.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.example.myapp.model.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@{user.image}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{user.firstName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
标签中的binding表达式表示为 "@{…}" 格式.上述表达式直接将用户的image,firstName,lastName赋值给view的source和text.这样就不用再写样板代码了.但是仍然不知道需要使用那个用户所以需要做分配:
private void setUser(User user, ViewGroup root) {
UserInfoBinding binding =
UserInfoBinding.inflate(getLayoutInflater(), root, true);
binding.setUser(user);
}
很简单!
从上述layout文件可以看到,View没有ID. 那我们在前面文章中试图生成的View Holder呢? 因为数据直接被绑定到了view上, 所以这里就不需要再去访问view了! 只是简单的设置变量,所有事情就完成了.
而且犯错的几率也变小了.例如, 你在横屏模式下没有用户图片,那么就不需要检查ImageView是否存在. 每个layout都会计算binding表达式, 如果没有ImageView,就不会执行更新代码.
这并不意味着View Holder就过时了. 还有很多时候你会需要直接访问view.只是这种情况比以前少了很多.
Include Layouts<a id="orgheadline5"></a>
那么, 包含的layout怎么办? 同样可以使用该功能, 就想View Holder模式一样.例如, 假设展示用户名称的TextView在一个被包含的layout中:
user_name.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.example.myapp.model.User"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<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>
可以在外层的layout中用如下方式来赋值user变量:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="user"
type="com.example.myapp.model.User"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@{user.image}"/>
<include
layout="@layout/user_name"
app:user="@{user}"/>
</LinearLayout>
</layout>
当user被设置时(通过代码 binding.setUser(…)), 被包含的layout的user变量也会被设置,因为设置了 *app:user="@{user}"*. 再次注意, 因为被包含的layout的view不需要被直接访问,(我甚至都没有设置id), 这里没有给include设置ID.
网友评论