你是否看過別人的layout并想:這個值在哪里設(shè)置和獲取.或者,你覺得不需要findViewById了是很好的一個開始,但仍然存在很多樣板代碼.Android Data Binding讓這個變得簡單.
使用ViewHolder模式<a id="orgheadline3"></a>
假設(shè)我們需要在應(yīng)用中顯示用戶信息. 在前面,我展示了使用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設(shè)置數(shù)據(jù):
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表達(dá)式來消除這些樣板代碼,
實現(xiàn)自動賦值.
給變量賦值<a id="orgheadline4"></a>
首先, 增加一個binding表達(dá)式需要的 data 標(biāo)簽以及一個相關(guān)變量.
然后, 對于layout中需要賦值的屬性, 使用binding表達(dá)式.
<?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>
標(biāo)簽中的binding表達(dá)式表示為 "@{…}" 格式.上述表達(dá)式直接將用戶的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呢? 因為數(shù)據(jù)直接被綁定到了view上, 所以這里就不需要再去訪問view了! 只是簡單的設(shè)置變量,所有事情就完成了.
而且犯錯的幾率也變小了.例如, 你在橫屏模式下沒有用戶圖片,那么就不需要檢查ImageView是否存在. 每個layout都會計算binding表達(dá)式, 如果沒有ImageView,就不會執(zhí)行更新代碼.
這并不意味著View Holder就過時了. 還有很多時候你會需要直接訪問view.只是這種情況比以前少了很多.
Include Layouts<a id="orgheadline5"></a>
那么, 包含的layout怎么辦? 同樣可以使用該功能, 就想View Holder模式一樣.例如, 假設(shè)展示用戶名稱的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>
當(dāng)user被設(shè)置時(通過代碼 binding.setUser(…)), 被包含的layout的user變量也會被設(shè)置,因為設(shè)置了 *app:user="@{user}"*. 再次注意, 因為被包含的layout的view不需要被直接訪問,(我甚至都沒有設(shè)置id), 這里沒有給include設(shè)置ID.