DataBinding實戰(三)
實戰
首先看一下之前程式碼
public class Goods {
public String name;
public String details;
public float price;
public Goods(String name, String details, float price) {
this.name = name;
this.details = details;
this.price = price;
}
}
非常簡單的Goods 類,只有幾個屬性。如果有一種情況,如果Goods 的name在設定了之後,又發生了變化,我需要更新顯示的name的View,怎麼辦?
這樣的程式碼已經達不到我們需要的效果,所以我要藉助DataBinding中的BaseObservable介面。
public class Goods extends BaseObservable { //如果是 public 修飾符,則可以直接在成員變數上方加上 @Bindable 註解 @Bindable public String name; //如果是 private 修飾符,則在成員變數的 get 方法上新增 @Bindable 註解 private String details; private float price; public Goods(String name, String details, float price) { this.name = name; this.details = details; this.price = price; } public void setName(String name) { this.name = name; //只更新本欄位 notifyPropertyChanged(com.lisn.mywanandroid.BR.name); } @Bindable public String getDetails() { return details; } public void setDetails(String details) { this.details = details; //更新所有欄位 notifyChange(); } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } }
從上面的程式碼看出,集成了BaseObservable介面之後,出現了三個新的方法:
notifyChange() :物件已經發生改變,所有繫結過該物件的view都需要重新整理。
notifyPropertyChanged(BR.name) : 物件的某一個屬性發生了改變,通過使用了這個屬性的view進行更新。
@Bindable : 把某一個物件的屬性繫結到BR檔案中,程式碼中對name進行了繫結,所以在BR中就出現了BR.name, 來直接找到這個屬性。
這樣就已經達到了我們想要的效果,其實DataBingding除了提供了可見介面來幫助我們實現這種效果,還提供了可見欄位:
ObservableBoolean, ObservableByte, ObservableChar
可見欄位是獨立欄位的可見物件,原始版本在訪問操作中避免裝箱和拆箱,為方便使用,在資料類建立中使用 pulic 。
下面來再次修改Goods 的程式碼:
public class ObservableGoods {
public ObservableField<String> name;
public ObservableFloat price;
public ObservableField<String> details;
public ObservableGoods(String name, float price, String details) {
this.name = new ObservableField<>(name);
this.price = new ObservableFloat(price);
this.details = new ObservableField<>(details);
}
}
非常的簡潔,看上去應該是對基本型別進行了一次包裝,使用起來非常簡便。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{observableGoods.price+"",default=price}'
android:textAllCaps="false" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{observableGoods.details,default=details}"
android:textAllCaps="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->observableGoodsHandler.changeGoodsName()}"
android:text="setName"
android:textAllCaps="false" />
使用中直接給observableGoods中name通過set方法設定值,對應的UI頁面也馬上自動更新,還可以通過成員變數的get()方法獲取屬性值。 observableGoods.name.set("newName");
字串拼接:
android:text='@{observableGoods.price+"",default=price}' 注意是單引號,漢字可以使用@string.name定義
可見集合
在提供了基本欄位以外,還提供了可見集合:
ObservableArrayMap和ObservableArrayList。
使用方法:
<data class="TestDataBinding2">
<import type="android.databinding.ObservableList" />
<import type="android.databinding.ObservableMap" />
<variable
name="observableMap"
type="ObservableMap<String,Object>" />
<variable
name="observableList"
type="ObservableList<Object>" />
<variable
name="key"
type="String"/>
</data>
注意轉義符 < 代表 < > 代表 >
type="ObservableList<Object>" 等於 type="ObservableList<Object>"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{observableMap["name"],default=observableMap}' />
<!--android:text='@{observableMap[key],default=observableMap}' />-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{observableList[0],default=observableList1}' />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{observableList[2],default=observableList2}' />
TestDataBinding2 mBinding = DataBindingUtil.setContentView(this, R.layout.activity_data_binding2);
......
ObservableList<Object> observableList = new ObservableArrayList<>();
observableList.add("name1");
observableList.add("name2");
observableList.add("name3");
observableList.add("name4");
mBinding.setObservableList(observableList);
mBinding.setKey("name");
ObservableArrayMap<String, Object> observableMap = new ObservableArrayMap<String, Object>();
observableMap.put("name", "hahahaha");
observableMap.put("detail", "aaaaaaaa");
mBinding.setObservableMap(observableMap);