DataBingding個人使用很久了,覺得很好用且方便,讓自己的代碼更加簡單且少,讀取來更有可讀性。建議還未入手的趕緊用起來,真的是方便快捷簡單。常規用法很簡單,我將使用中需要注意的地方進行一下總結和歸納。本篇文章適合DataBinding的進階和擴展學習。DataBinding的基礎學習地址爲:DataBinding中文官方文檔
關於DataBinding的基礎配置和原理請看:DataBinding的使用(一)
使用注意細節
雖然DataBinding使用簡單,但是還有些需要注意的地方,我將在下面意義列舉出來。
1.和TextView一樣,setText()類似,其中的數據不可是int或者Ingeter(或Int kotlin)、需要轉成String
<!--注意:這裏age是int類型,必須轉化爲String,否則會運行時異常-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(user.age)}" />
2.集合中的調用推薦用法
在使用List和Map中[]或者是get()兩種寫法,官方推薦這種集合框架使用[]的寫法
//這裏是單引號不是Tab上的點
android:text='@{map["key0"]}'
//或者這樣寫,注意:裏面的 ` 不是單引號,而是Tab鍵上面的那個鍵的那個點
android:text="@{map[`key0`]}"
3.java中的表達式支持
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
//和上面等價類似,如果user.displayName爲null,則右邊,否則左邊運行
2.還有如下 格式 ??符號相當於三目運算的簡寫
android:text="@{user.displayName ?? user.lastName}"
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
android:text='@{"iname:" +user.name}'
3.靜態方法的使用
<TextView android:text="@{MyStringUtils.capitalize(user.firstName)}" />
有時會報錯,此時使用android:text='@{@String/iname +user.name}'這種方式可解決
表達式語言與 Java 表達式有很多相似之處。下面是相同之處:
- 數學計算 + - / * %
- 字符串連接 +
- 邏輯 && ||
- 二進制 & | ^
- 一元 + - ! ~
- 位移 >> >>> <<
- 比較 == > < >= <=
- instanceof
- 組 ()
- 字面量 - 字符,字符串,數字, null
- 類型轉換
- 函數調用
- 字段存取
- 數組存取 []
- 三元運算符 ?:
不支持的操作符
一些 Java 中的操作符在表達式語法中不能使用。
- this
- super
- new
- 顯式泛型調用 <T>
4.設置別名alias
如果我們import了兩個不同路徑,但名稱相同的類,可以藉助於別名來解決,別名藉助alias字段來標識
<data>
<import type="com.zx.databindingdemo.bean.UserBean" />
<import type="com.zx.databindingdemo.bean.user.UserBean" alias="UserBean2"/>
<variable
name="user"
type="UserBean" />
<variable
name="user2"
type="UserBean2"/>
</data>
5.include中的數據傳遞
在使用命名空間的佈局中,變量可以傳遞到任何 include 佈局中
<data>
<variable name="user" type="com.example.User"/>
</data>
<include
layout="@layout/contact"
app:user="@{user}"/>
// 可以是app:user或者bind:user,其實都一樣的可以
6.Data binding不支持直接包含merge 節點。
//舉個例子, 以下的代碼不能正常運行 :
<merge>
<include layout="@layout/contact"
app:user="@{user}"/>
</merge>
7.事件處理使用方式
方式一:
android:onClick="@{clickListener}"
方式二:
//使用該種方法時末尾是沒有 "()"的,要特別注意
android:onClick="@{handler::onClickFriend}"/>
<!-- 注意:函數名和監聽器對象必須對應 -->
<!-- 函數調用也可以使用 `.` , 如handler.onClickFriend , 不過已棄用 -->
方式三
android:onCheckedChanged="@{(view,cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />
等價==
android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />
方式二相對於方式一,它的優勢在於表達式會在編譯時處理,如果方法不存在或者方法簽名不對,編譯將會報錯。
8.RecyclerView中的閃爍問題
@Override
public void onBindViewHolder(@NonNull UserAdapterHolder holder, int position) {
holder.getBinding().setClassName(beans.get(position));
holder.getBinding().setAdapter(this);
holder.getBinding().setPosition(position);
holder.binding.executePendingBindings();
}
holder.binding.executePendingBindings()這個不加上可能會控件顯示異常現象。
9.BindingAdapter註解設置自定義屬性
public class ImageHelper {
/**
* 1.加載圖片,無需手動調用此方法
* 2.使用@BindingAdapter註解設置自定義屬性的名稱,imageUrl就是屬性的名稱,
* 當ImageView中使用imageUrl屬性時,會自動調用loadImage方法,
*
* @param imageView ImageView
* @param url 圖片地址
*/
@BindingAdapter({"imageUrl"})
public static void loadImage(ImageView imageView, String url) {
Glide.with(imageView.getContext()).load(url)
.placeholder(R.mipmap.fruit)
.error(R.mipmap.fruit)
.into(imageView);
}
}
// 具體的使用形式
<!-- 當imageUrl屬性存在時,會自動調用ImageHelper的loadImage方法,
參數imageView爲當前使用imageUrl屬性的ImageView,參數url爲圖片地址 -->
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
app:imageUrl="@{user.picUrl}" />
10.onLongClick是有返回值
onLongClick的返回值類型是布爾型,故調用的方法應該也是有返回值且返回Boolean
//等待持續補充