作者:heiyulong
授權原文:https://mp。weixin。qq。com/s/n7VuWeZnx_1Ds5guMqsYSA
前言
Data Binding是一種支援庫,藉助該庫,您可以使用宣告性格式(而非程式化地)將佈局中的介面元件繫結到應用中的資料來源。
佈局通常是使用呼叫介面框架方法的程式碼在 Activity 中定義的。例如,以下程式碼呼叫 findViewById() 來查詢 TextView 控制元件並將其繫結到 viewModel 變數的 userName 屬性:
TextView textView = findViewById(R。id。sample_text); textView。setText(viewModel。getUserName());
以下示例展示瞭如何在佈局檔案中使用Data Binding 將文字直接分配到TextView。這樣就無需呼叫上述任何 Java 程式碼。請注意賦值表示式中 @{} 語法的使用:
注意
:
如果您使用Data Biding的主要目的是取代 findViewById() 呼叫,請考慮改用ViewBinding。
使用過ButterKnife的都知道,目前ButterKnife作者建議切換至ViewBindng使用;在許多情況下,ViewBinding可簡化實現,提高效能,提供與DataBinding相同的好處。
dataBinding 的優勢
雙向資料繫結
資料發生改變後,dataBinding 會自動通知 UI 重新整理頁面,不再需要人工繫結最新資料到 View 上。UI 改變後也能同步給資料。
減少模板程式碼
有了 dataBinding,從此不用再寫 findViewById,setOnClickListener 等枯燥生硬的程式碼,大大提高工作效率。從此 Butterknife 靠邊站。
釋放 Activity/Fragment
以前,我們在 Activity , Fragment 或 Presenter 中計算資料再繫結到 View 元件上,導致 View 層很臃腫,現在這部分工作我們可以直接在 xml 佈局檔案中完成。Activity , Fragment 讓它更加只關注核心業務。
資料繫結空安全
在 xml 中繫結資料它是空安全的,因為 dataBinding 在資料繫結上會自動裝箱和空判斷,所以大大減少了資料繫結帶來的 NullpointException 問題。
在使用 dataBinding 的時候,很多同學會誤以為不方便除錯;
現在的 databinding 在編譯階段也會有豐富的錯誤提示,在執行階段,我們可以根據佈局檔案找到實現類,跟進去斷點排查問題。
如fragment_layout_my。xml佈局,在編譯時會生成 FragmentLayoutMyImpl。java 實現類,我們可以搜尋這種類 debug 跟進解決問題。
Data Binding使用場景:
Data Binding使用前需要先引入
在app的build。gradle中加上以下程式碼即可,不用引用其他的依賴
android { 。。。 dataBinding { enabled = true }}
佈局和繫結表示式
資料繫結的佈局以根標記 layout 開頭,後跟 data 元素和 view 根元素。如下:
注意
:佈局表示式應保持精簡,因為它們無法進行單元測試,並且擁有的 IDE 支援也有限。為了簡化佈局表示式,可以使用自定義繫結介面卡。
<?xml version=“1。0” encoding=“utf-8”?>
==系統會為每個佈局檔案生成一個繫結類==。
1、預設情況下,類名稱基於佈局檔案的名稱,它會轉換為駝峰形式並在末尾新增 Binding 字尾。
2、以上佈局檔名為 activity_main。xml,因此生成的對應類為 ActivityMainBinding,==且都是ViewDataBinding的子類,所有佈局對應的生成的繫結類都可以是ViewDataBinding類==
3、此類包含從佈局屬性(例如,user 變數)到佈局檢視的所有繫結,並且知道如何為繫結表示式指定值。
4、建議的繫結建立方法是在擴充佈局時建立,如以下示例所示:
@Override protected void onCreate(Bundle savedInstanceState) { super。onCreate(savedInstanceState); //此時可以透過DataBindingUtil來設定Activity的頁面佈局。 //此時會返回一個ActivityMainBinding物件。 //這個是編譯時根據xml佈局檔案中的資料繫結自動生成的實現類。 ActivityMainBinding binding = DataBindingUtil。setContentView(this, R。layout。activity_main); User user = new User(“Test”, “User”); //完成資料繫結 binding。setUser(user); }
a、Activity 資料繫結 ( DataBinding ) :
1、DataBindingUtil類方法:
ActivityMainBinding binding = DataBindingUtil。setContentView(this, R。layout。activity_main);
2、生成的佈局繫結類的inflate()方法:
ActivityMainBinding binding = ActivityMainBinding。inflate(getLayoutInflater());
@Override protected void onCreate(Bundle savedInstanceState) { super。onCreate(savedInstanceState); //DataBindingUtil類方法 ActivityMainBinding binding = DataBindingUtil。setContentView(this, R。layout。activity_main); //生成的佈局繫結類的inflate()方法 //ActivityMainBinding binding = ActivityMainBinding。inflate(getLayoutInflater()); User user = new User(“Test”, “User”); binding。setUser(user); }
b、 Fragment、ListView 或 RecyclerView 介面卡中使用資料繫結 ( DataBinding )
DataBindingUtil 或 生成的佈局繫結類deinflate() 方法,如以下程式碼示例所示:
ListItemBinding binding = ListItemBinding。inflate(layoutInflater, viewGroup, false); // or ListItemBinding binding = DataBindingUtil。inflate(layoutInflater, R。layout。list_item, viewGroup, false);
Data Binding繫結表示式:
xml裡支援使用以下表達式:
算術運算子 + - / * %
字串連線運算子 +
邏輯運算子 && ||
二元運算子 & | ^
一元運算子 + - ! ~
移位運算子 >> >>> <<
比較運算子 == > < >= <=(請注意,< 需要轉義為 <)
instanceof
分組運算子 ()
字面量運算子 - 字元、字串、數字、null
型別轉換
方法呼叫
欄位訪問
陣列訪問 []
三元運算子 ?:
不支援以下表達式:
this
super
new
顯式泛型呼叫
a、變數
1、生成的資料繫結程式碼會自動檢查有沒有 null 值並避免出現 Null 指標異常。
2、例如,在表示式 @{user。name} 中,如果 user 為 Null,則為 user。name 分配預設值 null。
3、如果您引用 user。age,其中 age 的型別為 int,則資料繫結使用預設值 0。
<!——變數給控制元件賦值——>android:text=“@{user。name}”<!——控制元件給變數賦值(雙向繫結)——>android:text=“@={user。name}”
b、Null 合併運算子(空運算子)
如果左邊運算數不是 null,則 Null 合併運算子 (??) 選擇左邊運算數,如果左邊運算數為 null,則選擇右邊運算數。
android:text=“@{user。displayName ?? user。lastName}”//等效於如下三目表示式android:text=“@{user。displayName != null ? user。displayName : user。lastName}”
c、檢視引用
1、表示式可以透過以下語法按 ID 引用佈局中的其他檢視:
2、繫結類將 ID 轉換為駝峰式大小寫。
3、在以下示例中,TextView 檢視引用同一佈局中的 EditText 檢視:
android:text="@{exampleText.text}"
d、顯示隱藏控制
1、首先在 xml 的 data 節點中引用View
2、然後設定visibility
e、事件處理
方法引用:
==android:onClick=“@{handlers::onClickFriend}”==
繫結表示式可將檢視的點選監聽器分配給MyHandlers 類的 onClickFriend() 方法,如下所示:
public class MyHandlers { public void onClickFriend(View view) { 。。。 } }
<?xml version=“1。0” encoding=“utf-8”?>
注意:
1、在表示式中,您可以引用符合監聽器方法簽名的方法。
2、當表示式求值結果為方法引用時,資料繫結會將方法引用和所有者物件封裝到監聽器中,並在目標檢視上設定該監聽器。
3、如果表示式的求值結果為 null,則資料繫結不會建立監聽器,而是設定 null 監聽器。
4、表示式中的方法簽名必須與監聽器物件中的方法簽名完全一致。
監聽器繫結:
==android:onClick=“@{() -> presenter。onSaveClick(task)}”==
繫結表示式可將檢視的點選事件繫結打給Presenter 類的 onSaveClick(Task task) 方法,如下所示:
public class Presenter { public void onSaveClick(Task task){} }
<?xml version=“1。0” encoding=“utf-8”?>
以上,我們尚未定義傳遞給 onClick(View) 的 view 引數。
監聽器繫結提供兩個監聽器引數選項:您可以忽略方法的所有引數,也可以命名所有引數。
如果您想命名引數,則可以在表示式中使用這些引數。
例如,上面的表示式可以寫成如下形式:
android:onClick=“@{(view) -> presenter。onSaveClick(task)}”
或者,如果您想在表示式中使用引數,則採用如下形式:
public class Presenter { public void onSaveClick(View view, Task task){} }
android:onClick=“@{(theView) -> presenter。onSaveClick(theView, task)}”
監聽長按事件,表示式應返回一個布林值。
public class Presenter { public boolean onLongClick(View view, Task task) { } } android:onLongClick=“@{(theView) -> presenter。onLongClick(theView, task)}”
注意:
1、監聽器繫結這些是在事件發生時進行求值的 lambda 表示式。
2、資料繫結始終會建立一個要在檢視上設定的監聽器。
3、事件被分派後,監聽器會對 lambda 表示式進行求值。
dataBinding 可以拓展 View 屬性
以前想要給 ImageView 增加幾個屬性,必須要寫個自定義的 ImageView 在建構函式中一頓解析。
那看看使用 dataBinding 如何拓展 View 屬性。
public class CustomImageView extends ImageView{ //需要使用BindingAdapter註解並標記在public static方法上。 //value中的欄位隨意新增和方法引數一一對應即可。 @BindingAdapter(value = {“image_url”, “isCircle”}) public static void setImageUrl(PPImageView view, String imageUrl, boolean isCircle) { view。setImageUrl(view, imageUrl, isCircle, 0); } //requireAll = false代表是否以下三個屬性在xml中同時使用才會呼叫到該方法 //為false的話,只要有一個屬性被使用就能呼叫到該方法 @BindingAdapter(value = {“image_url”, “isCircle”, “radius”}, requireAll = false) public static void setImageUrl(PPImageView view, String imageUrl, boolean isCircle, int radius) { …… } }//在佈局檔案中如下使用,便能實現圖片圓角和資源Url繫結的功能
BindingAdapter
繫結介面卡,是 Jetpack DataBinding 中用來擴展布局 xml 屬性行為的註解;
允許你針對佈局 xml 中的一個或多個屬性進行繫結行為擴充套件;
這個屬性可以是自定義屬性,也可以是原生屬性。
這個擴充套件行為可以是簡單的ViewModel屬性與控制元件賦值繫結,也可以是關聯某個控制元件屬性的額外操作,
例如在設定屬性之前進行值域檢查,或型別轉換,或者統一處理一些事情。
後臺私信回覆 1024 免費領取 SpringCloud、SpringBoot,微信小程式、Java面試、資料結構、演算法等全套影片資料。