看一看 DataBinding

最近在看一些人寫的代碼,發現不少都有用到 DataBinding,往往看到 DataBinding 相關的代碼看不懂,摸不透,實在是難受啊,但是怎麼辦呢,誰讓本身不會的呢。沒辦法開始學吧,不要求會太多,總得能看的懂人家寫的是啥意思吧。java

本篇難度屬於 DataBinding 入門級別,若是有什麼錯誤,還請指正。要學習 DataBinding 最好的教材仍是經過官方給的實例教程android

正式開始以前呢,老是得添加依賴,不過,DataBinding 的依賴可不像 RxJava 或是其餘庫經過引入兩行依賴,而是經過在 app.gradle 文件中引入下面的配置:git

android {
    ...
    dataBinding {
        enabled = true
    }
}
複製代碼

有了依賴以後,咱們就能夠開始了,如今想象一個場景,咱們須要把一段文字顯示在 TextView 上。以前,咱們都是經過 findViewById,而後 setText,現現在來一塊兒看看 DataBinding 是怎麼作的吧。github

首先,咱們須要把佈局文件的結構進行改造一下,改形成這樣的結構。express

<layout>
    <data>
    </data>
    <ViewGroup>
    </ViewGroup>
</layout>
複製代碼

Android Studio 對 DataBinding 有自動替換的支持。app

image-20190718101219778

替換以後的 ViewGroup 就是以前的根佈局,data 節點內用於定義數據。框架

<data>
    <variable name="content" type="String" />
</data>
複製代碼

以此形式定義的變量 content 等價於 String content。拿到了 content 這個變量,緊接着就須要設置到 TextView 上。設置 Text,使用的屬性是 android:text="" 至於填入的值,就是 content,不過語法上稍有不一樣,android:text="@{content}" 其中 @ 以及{}是用於包裹其中的值,以此來區分開 android:text="content"ide

Databinding 使用這種語法來設置內容,事實上這種表達方法不只僅用於設置個字符串,還支持表達式,更多內容請參考官方文檔。本文也會介紹一些。佈局

事實上,咱們更多時候會把 content 做爲一個類的成員變量。只要將 variable 的 type 屬性改爲對應的類名,同時在 TextView 上改成 android:text="@{detail.content}" 便可。post

<data>
    <variable name="detail" type="me.monster.blogtest.model.MomentDetail" />
</data>
複製代碼

在佈局文件中定義好了變量,如今咱們該回到 Java 文件中將佈局文件使用 DataBinding 進行綁定上數據了。

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        FragmentDetailBinding viewDataBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_detail, container, false);
        View root = viewDataBinding.getRoot();
        mMomentDetail = new MomentDetail();
  			mMomentDetail.setContent("使用 DataBinding");
        viewDataBinding.setDetail(mMomentDetail);
        return root;
    }
複製代碼
  1. 這段代碼是使用在 Fragment 中的,若是在 Activity 中,則使用 DataBinding.Util.setContentView(Activity activity, int layoutId) 這個方法。
  2. FragmentDetailBinding 這個類是根據佈局文件生成的,類名的規則是佈局文件的文件名+Binding;

DataBinding 這樣使用,好像不太夠平常使用。當 mMomentDetail 內部的 content 發生改變時,TextView 能自動更新嗎?暫時不行,想讓 TextView 自動更新 mMomentDetail 的 content 的內容,咱們還須要另外的一些東西。

要想及時更新 mMomentDetail 的 content 內容,按照以往的作法,就是在更新 mMomentDetail 的 content 內容時,手動調用 setText() 這個方法。如今有了 DataBinding 就不用了。咱們能夠把 mMomentDetail 的 content 定義爲一種可觀察其變化的類型,而後經過 DataBinding 就能自動完成對 TextView 上內容的更新。

public class MomentDetail {    
    private String content;

    public String getContent() {
        return content == null ? "" : content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
複製代碼

這個是 TextView 不能自動更新內容的 MomentDetail 類,要想讓 TextView 自動更新,只須要把 content 的類型改變便可。改成 ObservableField<String> content

private ObservableField<String> content = new ObservableField<>();

public ObservableField<String> getContent() {
    return content;
}

public String getContentValue() {
    return content.get();
}

public void setContent(String content) {
    this.content.set(content);
}
複製代碼

與普通的 String 類型不一樣的是,想要改變 content 的值,須要調用 ObservableField.set(T t) 方法,獲取其中的值則使用 ObservableField.get() 方法。

DataBinding 還包含了一些其餘的類,都是同樣的用法。

  • ObservableBoolean
  • ObservableByte
  • ObservableChar
  • ObservableShort
  • ObservableInt
  • ObservableLong
  • ObservableFloat
  • ObservableDouble
  • ObservableParcelable

我在寫這篇博客的時候,使用 Handler 延遲幾秒鐘對 MomentDetail 進行修改,用於模擬點擊事件。

當咱們用於觀察的數據較多的時候,還能夠經過將自定義的數據類繼承 BaseObservable ,產生繼承關係以後,數據類中的成員變量都可以在發生改變時自動應用到 View 上。

public class MomentDetail extends BaseObservable {
    private String moment;
    private int goodCount;

    @Bindable
    public String getMoment() {
        return moment == null ? "" : moment;
    }

    @Bindable
    public int getGoodCount() {
        return goodCount;
    }

    public void setContent(String msg) {
        this.moment = msg;
        notifyPropertyChanged(BR.moment);
    }

    public void updateGood(int count) {
        goodCount = count;
        notifyPropertyChanged(BR.goodCount);
    }
}
複製代碼

跟其餘的數據類沒有什麼太大的差距,只是多了一個註解 @Bindable 以及在成員變量進行更改後進行更新 notifyPropertyChanged()。不過,Google 仍是推薦使用 LiveData 配合使用。

public class MomentViewModel extends ViewModel {

    private MutableLiveData<String> name = new MutableLiveData<>("Abs");
    private MutableLiveData<Integer> good = new MutableLiveData<>();

    public void setNameValue(String value) {
        name.setValue(value);
    }

    public MutableLiveData<String> getName() {
        return name;
    }

    public MutableLiveData<Integer> getGood() {
        return good;
    }

    public void setGoodValue(int goodValue) {
        good.setValue(goodValue);
    }
}
複製代碼

相應的,佈局文件中也要進行更改數據類型。

<variable name="viewModel" type="me.monster.blogtest.model.MomentViewModel" />
複製代碼

DataBinding 設置 View 的 texttextColor 等屬性均可以直接經過相似 android:text="@{viewModel.name}" 這種形式來進行操做,那若是想對控件進行點擊事件的監聽怎麼辦呢?也不麻煩,咱們只須要提供一個用於處理點擊結果的方法便可。

例如,咱們有一個 TextView 用於進行點擊,並將點擊次數顯示在當前 TextView 上。

public void upGood() {
    good.setValue(good.getValue() == null ? 1 : good.getValue() + 1);
}
複製代碼
<TextView android:id="@+id/iv_good" android:layout_width="wrap_content" android:layout_height="40dp" android:drawableStart="@drawable/ic_good" android:drawablePadding="8dp" android:gravity="center" android:onClick="@{() -> viewModel.upGood()}" android:text="@{String.valueOf(viewModel.good)}" />
複製代碼

不過,DataBinding 雖然挺好的,可是仍是有些不足,好比經過 Glide 這種第三方框架加載圖片,仍是得 findViewById,事實上,DataBinding 提供了另外一種解決思路,經過將一個靜態方法加上註解,而後就能夠在 View 中進行使用。

@BindingAdapter({"imageRes"})
public static void loadImage(ImageView imageView, int resId) {
    Glide.with(imageView)
            .load(resId)
            .into(imageView);
}
複製代碼
<ImageView android:id="@+id/iv_avatar" imageRes="@{viewModel.avatar}" android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/avatar_1" />
複製代碼

BindAdapter 還有更多其餘用法,請參考官方文檔

總體來講,DataBinding 不難,並且入門也挺簡單的,不過,剛上手,不少時候摸不到頭腦。不過,它的好處也很明顯,在 Fragment 或是 Activity 中沒有使用任何直接或是間接的 findViewById 操做。保證了 Activity 與 Fragment 的簡潔,使其能更好的專一於頁面的跳轉及數據的處理,假若配合着 Jetpack 的其餘組件協同開發,估計會更高效些。

本文旨在學習如何簡單的使用 DataBinding,主體內容較爲簡單,實際上,平常開發中還會常常用到 RecyclerView 及其餘功能,DataBinding 也能提供很好的支持,有興趣或是須要的話能夠自行查閱官方文檔

文章首發於我的博客,文中全部代碼均已上傳至 GitHub,代碼分支爲:dataBinding。

相關文章推薦:

本文封面圖:Photo by Paul Schafer on Unsplash

相關文章
相關標籤/搜索