BindingAdapter :綁定適配器,是 Jetpack DataBinding 中用來擴展布局 xml 屬性行爲的註解,容許你針對佈局 xml 中的一個或多個屬性進行綁定行爲擴展,這個屬性能夠是自定義屬性,也能夠是原生屬性。這個擴展行爲能夠是簡單的ViewModel屬性與控件賦值綁定,也能夠是關聯某個控件屬性的額外操做,例如在設置屬性以前進行值域檢查,或類型轉換,或者統一處理一些事情。
例:java
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@{"http://****/**.jpg"}" />
上例中:src是默認的控件屬性,而src須要使用一個資源ID,來完成賦值,並不支持網絡地址來獲取設置圖片,此時就能夠經過 BindingAdapter 來擴展行爲,使其具有使用一個網絡地址,而且從網絡下載圖片並顯示的能力。android
@BindingAdapter("android:src") public static void setSrc(ImageView view, String bitmapPath) { if(ObjectUtil.nonNull(bitmapPath)) { GlideApp.with(view.getContext()) .load(bitmapPath) .into(view); } else { view.setImageDrawable(null); } }
這樣就完成了對於 android:src 佈局屬性的行爲擴展。此時咱們能夠直接設置地址路徑來完成網絡下載圖片並複製給 ImageView 的能力了。編程
BindingAdapter 是基於 APT 註解技術工做的,APT 能夠在項目構建時更具相關編寫規則生成特定代碼完成一些指定功能的技術。
BindingAdapter 有兩個屬性,value 是一個 String[] ,requireAll 是一個boolean類型:
value 用來描述 XML 中感興趣的關聯屬性,這裏是個數組,說明一個擴展方法能夠同時關注多個 XML 屬性。這個很重要,有時候咱們可能在對控件進行賦值時,須要同時給定多個值,而 XML 屬性值卻一次只能指定一個變量,這樣可能會讓咱們不的不爲此去擴展一個複合對象來完成這樣的賦值,可是實際上並不須要那樣。
requireAll 用來對 value 補充說明的,這個值默認是 true,表示使用這個適配規則必須在 XML 中聲明該註解關注全部屬性值,不然編譯時會報錯,而 false 則不須要,他容許只使用關注的部分或所有屬性來使用該規則。數組
例: 當requireAll = true 時網絡
@BindingAdapter(value = {"galleryEffectWidthLeft", "galleryEffectWidthRight", "galleryEffectPageMargin", "galleryEffectScale"}, requireAll = true) public static void setBannerGalleryEffect(Banner banner, int galleryWidthLeft, int galleryWidthRight, int galleryPageMargin, float galleryScale) { banner.setBannerGalleryEffect(galleryWidthLeft, galleryWidthRight, galleryPageMargin, galleryScale); }
//正確 galleryEffect 相關4個熟悉都設置了 <com.youth.banner.Banner android:layout_width="match_parent" android:layout_height="175dp" android:layout_marginTop="90dp" app:adapter="@{recommendVipZoneViewModel.bannerAdapter}" app:banner_radius="8dp" app:galleryEffectWidthLeft="@{7}" app:galleryEffectWidthRight="@{8}" app:galleryEffectPageMargin="@{9}" app:galleryEffectScale="@{0.85f}" /> //錯誤,app:galleryEffectScale 屬性未設置狀況 <com.youth.banner.Banner android:layout_width="match_parent" android:layout_height="175dp" android:layout_marginTop="90dp" app:adapter="@{recommendVipZoneViewModel.bannerAdapter}" app:banner_radius="8dp" app:galleryEffectWidthLeft="@{7}" app:galleryEffectWidthRight="@{8}" app:galleryEffectPageMargin="@{9}" />
例: 當requireAll = false 時app
@BindingAdapter(value = {"galleryEffectWidthLeft", "galleryEffectWidthRight", "galleryEffectPageMargin", "galleryEffectScale"}, requireAll = false) public static void setBannerGalleryEffect(Banner banner, int galleryWidthLeft, int galleryWidthRight, int galleryPageMargin, float galleryScale) { banner.setBannerGalleryEffect(galleryWidthLeft, galleryWidthRight, galleryPageMargin, galleryScale); }
//正確,須要注意的是,此時少了的galleryEffectScale屬性可能會接受一個默認只好比這裏float可能爲0.0 <com.youth.banner.Banner android:layout_width="match_parent" android:layout_height="175dp" android:layout_marginTop="90dp" app:adapter="@{recommendVipZoneViewModel.bannerAdapter}" app:banner_radius="8dp" app:galleryEffectWidthLeft="@{7}" app:galleryEffectWidthRight="@{8}" app:galleryEffectPageMargin="@{9}" />
關於 BindingAdapter 註解自己已經有所瞭解。如何使用
首先,關於使用 BindingAdapter 描述的函數簽名,參數列表必須按照如下固定形式出現:ide
// 類構建能夠隨意,APT會在構建時掃描全局代碼 public class ViewAttrAdapter { // 須要注意的是 XML標籤 關注了幾個,參數列表就須要寫幾個對應的接受參數。且關注控件類必須在第一個參數。 @BindingAdapter({xml屬性標籤, ...}) public static void 函數名(關注的控件類 view, xml屬性標籤值 value, ...){ // 行爲 } // 能夠包含多個函數 ..... }
而在XML佈局中,咱們應該使用 BindingAdapter 標籤對應的標籤類型進行賦值,切必須使用@{}做爲值包裹,這是爲了提供給APT解析XML是區別普通賦值的方式。函數
<View android:layout_width="match_parent" android:layout_height="175dp" app:xml屬性標籤="@{函數參數接受類型的值}" />
須要注意的是綁定解析的觸發規則:佈局
// 這個限定使用時必定是android:src才能匹配 @BindingAdapter("android:src") // 這個限定使用時 app:src 和 android:src 均可以匹配,但須要注意的是,android必須是在自定義屬性聲明的XML中有描述過的,如 attrs.xml 中 @BindingAdapter("src")
觸發解析的屬性必須知足 標籤="@{value}" 這裏的 @{} 必定不能丟。學習
最後總結:BindingAdapter 提供了一個高自由的切片編程能力,容許在xml解析是綁定擴展行爲,能夠幫助完成不少事情,如事件監聽,屬性賦值,類型轉換,統一業務處理,好比埋點處理,防重按等等。而 BindingAdapter 僅僅是Databinding中一個使用較多的註解,以後會學習更多相關注解幫助擴展雙向綁定,雙向賦值之類的事情。(一上屬於我的理解,若有不一樣想法,能夠溝通修改,也會不時更新)