Android DataBinding基本用法

Learning By Doing

一個Demo掌握DataBinding的基本用法

前言

DataBinding 是Google推出的一個支持庫,它的作用是:通過layout文件綁定app邏輯和UI的更新,儘可能地減少編碼工作。

說定義似乎有些隱晦,還是通過learning by doing的方式來學習吧。

這篇文章包括以下幾方面的內容:

  • 通過layout來綁定app邏輯
  • layout裏包含include標籤的用法
  • 點擊事件的處理
  • 使用Observablues動態更新UI
  • 使用ObervablueFields動態更新UI

我會按照上面列的順序,一步步在Demo裏面實現對應的功能

所有的源碼都包含在這篇文章裏,需要Demo的可以評論留言

由於是Learning By Doing,所以不會有理論的講解,關於爲什麼是layout便籤,爲什麼支持這樣調用等問題,請去Android Developer 看官方文檔,或者去Stack Overflow 提問

通過layout來綁定app邏輯

注意:

首先打開Andriod Studio,並創建一個新的項目,然後再正式開始我們的DataBinding之旅。

加入Databinding

在app/gradle文件中加入:

Databinding{
    Eanbled = true
}

就可以使用DataBinding了,前提是你的Android Studio是2.1.3以上的版本(目前最新版已經是3.1.4了~)

編寫Bean

這裏我們用User類來演示

public class User {

    private String name;
    private String email;

    public String getName() {
        return name == null ? "" : name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email == null ? "" : email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

}

Android Stuido: command/ctrl + n 快捷鍵 可以快速創建構造方法,gettet/setter方法等

編寫layout文件

打開activity_main.xml 文件,把根目錄改成layout,並且加入data 和 variable 標籤

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:bind="http://schemas.android.com/tools">

    <data>
        <variable
            name="user"
            type="com.blue.androidlearningcode.databinding.User"/>

    </data>

     <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}" />

        <TextView
            android:id="@+id/email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.email}" />
</layout>
  • layout data variables的官方定義:

    The Data Binding Library automatically generates the classes required to bind the views in the layout with your data objects. The library provides features such as imports, variables, and includes that you can use in your layouts.

  • data:用於定義在DataBinding裏面需要用到的數據對象(data objects)

  • variable:比data更小的層級,通常是class,我們這裏就是剛剛寫的User類
  • textview: 通過@{user.xxx}來綁定user裏面的屬性

在代碼中綁定xml裏面的控件

回到MainActivity.class文件中,現在我們需要做的就是把剛剛寫的layout文件,和生成的DataBinding綁定起來。

首先,讓我們愉快的 clean & rebuild project

爲什麼呢? 因爲DataBinding需要在Build的過程中生成綁定類

ps:實際開發中,如果項目過大,可能Restart Android Studio比較快。。

OK,如果一切順利的話,就開始寫MainActivity的代碼吧,在onCreate方法中:

  ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        user = new User();
        user.setName("BlueLzy");
        user.setEmail("[email protected]");

        binding.setUser(user);
  • ActivityMainBinding:這貨就是Build完生成出來的東西
  • binding.setUser():綁定對應的bean

好了,run一下,應該就能看到在兩個TextView中分別出現了name和email的value了

layout裏包含include標籤的用法

上面的用法其實就是DataBinding最基本的用法,通過xml和class的綁定,減少我們在class裏面編寫的代碼量。

但是理想很豐滿,現實很骨感,項目中總是會有許多意想不到的需求,例如:我要在layout裏面使用include標籤,咋整?

如果直接把include標籤加入到父佈局,然後運行程序,你會發現是不行的,我們有些小細節要處理。

So,let‘s do it.

新建content_data_binding.xml

在layout文件夾下新建一個佈局文件,用於存放我們需要用到的view

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android" >

    <data>
        <variable
            name="user"
            type="com.blue.androidlearningcode.databinding.User"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}" />

        <TextView
            android:id="@+id/email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.email}" />

    </LinearLayout>

</layout>

可以看到,其實我們就是把activity_main.xml的兩個TextView搬到了這個新的layout中。

修改activity_main.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:bind="http://schemas.android.com/tools">

    <data>
        <variable
            name="user"
            type="com.blue.androidlearningcode.databinding.User"/>

    </data>

        <include
            android:id="@+id/content"
            layout="@layout/content_data_binding"
            bind:user="@{user}" />

</layout>

其實使用include標籤要注意的地方就是:

  1. 父佈局的include標籤需要加上: bind:user=”@{user}” ,通過這行代碼來關聯bean和layout
  2. 子佈局也需要加上layout,data,variable等標籤

OK,再次運行程序,我們會發現效果和上面的一樣,顯示出來了name和email的值。

點擊事件的處理

上面的Demo只是靜態的,還無法對view的onClick,onLongClick 或者其他方法進行響應,那麼接下來我們首先處理的就是onClick事件

修改MainActivity

創建MyClickHandlers內部類

在FAB點擊的時候彈出Toast

   public class MyClickHandlers {

        public void onFabClicked(View view){
            Toast.makeText(getApplicationContext(), "FAB clicked!", Toast.LENGTH_SHORT).show();
        }
    }

修改activity_main.xml

我們在這裏使用FAB(FloatingActionButton)來演示:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:bind="http://schemas.android.com/tools">

    <data>
        <variable
            name="user"
            type="com.blue.androidlearningcode.databinding.User"/>

        <variable
            name="handlers"
            type="com.blue.androidlearningcode.DataBindingTestActivity.MyClickHandlers"/>
    </data>

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include
            android:id="@+id/content"
            layout="@layout/content_data_binding"
            bind:user="@{user}" />

        <android.support.design.widget.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="20dp"
            app:srcCompat="@android:drawable/ic_dialog_info"
            android:onClick="@{handlers::onFabClicked}"/>
    </android.support.design.widget.CoordinatorLayout>

</layout>

綁定MyClickHandlers

又來到了clean & rebuild 時刻,在onCreate()裏面進行綁定

MyClickHandlers handlers = new MyClickHandlers();
binding.content.setHandlers(handlers);  // binding content layout click event
  • 爲什麼上面的User是binding.setUser(),而這裏是binding.content.setHandlers()呢:

    這個問題很有趣,細心的童鞋應該是可以發現的,原因在xml的代碼裏

OK,let‘s run it!!!

Sep-09-201820-50-31.gif

我們雖然沒有在代碼裏面重寫onClickListener和onClick方法,但是通過DataBinding的方式還是成功實現了view的onClick(),至於上面的name和email的更新,就是下面要講的了。

使用Observablues動態更新UI

推動人類進步的,其實是懶惰。爲了能夠少寫兩行代碼,人類總是可以發明出各種新技術。例如:Observablues

Question:有沒有辦法在數據變化的時候讓UI自動刷新呢?

答案當然是有的,let me show you:

修改User類

public class User extends BaseObservable{

    private String name;
    private String email;

    @Bindable
    public String getName() {
        return name == null ? "" : name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

    @Bindable
    public String getEmail() {
        return email == null ? "" : email;
    }

    public void setEmail(String email) {
        this.email = email;
        notifyPropertyChanged(BR.email);
    }

}
  • User繼承BaseObservable
  • 每個getter()加上註解@Bindable
  • 每個setter()加上notifyPropertyChanged(BR.xxx); - BR在rebuild後自動生成

修改MainActivity

我們只需要改一個地方:onFabClicked()

        public void onFabClicked(View view){
            Toast.makeText(getApplicationContext(), "FAB clicked!", Toast.LENGTH_SHORT).show();
            user.setName("BlueLzyzzz");
            user.setEmail("[email protected]");
        }

我們並沒有給textview設置text,而是給user的name和email重新賦值,看一下在FAB點擊的時候UI會不會跟隨data進行動態刷新。

run the project 。。。。。and 回頭看上面的動圖,哈哈哈~

使用ObervablueFields動態更新UI

其實上面已經把DataBinding的基本用法講的差不多了,通過實踐的方式一步步學習DataBinding,我覺得還是比較快速和容易上手的。

至於ObervablueFields,它其實也是爲了能夠減少代碼量,當一個Bean沒有那麼多屬性的時候,我們不需要寫這麼多的get和set方法,使用ObervablueFields只需要通過兩行代碼即可實現相同效果。

下面是Demo:

修改User類

加上age屬性:

    // 使用ObservableField
    public static ObservableField<String> age = new ObservableField<>();

    public static ObservableField<String> getAge() {
        return age;
    }

修改content_data_binding.xml

多加一個TextView

        <TextView
            android:id="@+id/age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.age}" />

修改MainActivity

修改onFabClicked()

        public void onFabClicked(View view){
            Toast.makeText(getApplicationContext(), "FAB clicked!", Toast.LENGTH_SHORT).show();
            user.setName("BlueLzyzzz");
            user.setEmail("[email protected]");
            User.age.set("20");
        }

其實就是多加了一行,User.age.set(“20”); 因爲age是靜態變量,所以可以直接引用。

效果嘛。。還是回頭看動圖吧~~~

在實際項目中,通常一個API返回的Bean都會有十幾個屬性,多的可能有幾十個,我們不可能一個個去寫getter和setter還有@Bindable,這時候可以通過ObervablueFields來減少工作量,也可以通過插件來自動生成需要的代碼。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章