1. 程式人生 > >DataBinding實戰(三)

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

等基本資料型別,還包括物件型別ObservableField等。

可見欄位是獨立欄位的可見物件,原始版本在訪問操作中避免裝箱和拆箱,為方便使用,在資料類建立中使用 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&lt;String,Object&gt;" />

        <variable
            name="observableList"
            type="ObservableList&lt;Object&gt;" />

        <variable
            name="key"
            type="String"/>

    </data>

注意轉義符  &lt;  代表   &gt; 代表 >

type="ObservableList&lt;Object&gt;"   等於  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);