Android DataBinding之初體驗

lowett發表於2019-02-21

(一)

關於DataBinding

Google推出DataBinding有一段時間,但是目前來看沒有幾個人用(尷尬),當然Google推出很多東西都沒使用者(哈哈),不過作為程式猿
學習這個東西還是很有必要的,畢竟技術的革新都是在一點點試錯中發展壯大。此係列參考官方文件。
說明:
支援:Android 2.1 (API level 7+)
要求:Gradle外掛至少1.5.0-alpha1或更高,Android Studio 1.3+

構建環境

使用之前要先從Support respository下載支援包,不過現在基本上都有的,沒有support還怎麼玩。
讓後在app模組的build.gradle中新增如下:

    android {
        ....
        dataBinding {
            enabled = true
        }
    }複製程式碼

注意:如果使用了library,而這個庫使用了databinding,主模組也要配置。

佈局檔案

databinding的佈局檔案是區別於傳統的layout檔案,跟節點是以layout開頭的,e.g.

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
       <data>
           <variable name="user" type="com.example.User"/>
       </data>
       <LinearLayout
           android:orientation="vertical"
           android:layout_width="match_parent"
           android:layout_height="match_parent">
           <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="@{user.firstName}"/>
           <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="@{user.lastName}"/>
       </LinearLayout>
    </layout>複製程式碼

data節點中定義變數名稱,type是變數的型別(全名:包名+類名)。
而使用這個變數類似:

    <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="@{user.firstName}"/>複製程式碼

Data Object

上面已經寫好了佈局檔案,已經定義了user變數,下面我們就定義一個User類,

    public class User {
        // public final 
       public final String firstName;
       public final String lastName;
       public User(String firstName, String lastName) {
           this.firstName = firstName;
           this.lastName = lastName;
       }
    }複製程式碼

這樣寫的實體通常是不會變化的,就跟我們平日寫的JavaBean一樣,但是欄位必須是public和final的,還有另一種寫法

    public class User {
        // private final 但是有getter
       private final String firstName;
       private final String lastName;
       public User(String firstName, String lastName) {
           this.firstName = firstName;
           this.lastName = lastName;
       }
       public String getFirstName() {
           return this.firstName;
       }
       public String getLastName() {
           return this.lastName;
       }
    }複製程式碼

繫結資料

預設定義好了layout就會生成一個以“Binding”結尾同名的丙丁物件,讓後通過DataBindingUtil來將layout和Activity繫結。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
       User user = new User("Test", "User");
       binding.setUser(user);
    }複製程式碼
  1. 將layout和Activity繫結
  2. 建立一個實體
  3. 將實體和佈局關聯起來

執行

上面簡單幾步,建立了一個DataBinding App現在執行起來,看看效果。

事件處理

上面只是一個簡單的示例,畢竟沒有人寫一個只做展示而沒有互動的應用,有互動必然有事件處理。DataBinding同樣可以處理這些。

  1. 方法引用
  2. 監聽繫結

    方法引用

  3. 定義一個類
     public class MyHandlers {
         public void onClickFriend(View view) { 
             Toast.makeText(view.getContext(), "Hello World", Toast.LENGTH_SHORT).show();
         }
     }複製程式碼
  4. 修改佈局檔案
     <?xml version="1.0" encoding="utf-8"?>
     <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <variable name="handlers" type="com.example.Handlers"/>
            <variable name="user" type="com.example.User"/>
        </data>
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{user.firstName}"
                android:onClick="@{handlers::onClickFriend}"/>
        </LinearLayout>
     </layout>複製程式碼

    data節點申明變數,和型別
    andorid:onClick中呼叫函式,

  5. 賦值
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
         User user = new User("Test", "User");
         binding.setUser(user);
         binding.setHandlers(new MyHandlers()); // 給變數賦值
     }複製程式碼

    這樣我們的時間就繫結好了,我們執行點選,就會彈出Toast。
    說明:如果沒有賦值,不會報錯,也不會彈出Toast,相當於沒有繫結事件。

監聽繫結

這種方式只有在Gradle外掛version 2.0+上才能使用。

  1. 定義監聽類
    Task表示回撥引數
     public class Presenter {
         public void onSaveClick(Task task){}
     }複製程式碼
  2. 修改layout檔案
       <?xml version="1.0" encoding="utf-8"?>
       <layout xmlns:android="http://schemas.android.com/apk/res/android">
           <data>
               <variable name="task" type="com.android.example.Task" />
               <variable name="presenter" type="com.android.example.Presenter" />
           </data>
           <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
               <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
               android:onClick="@{() -> presenter.onSaveClick(task)}" />
           </LinearLayout>
       </layout>複製程式碼

    android:onClick=”@{() -> presenter.onSaveClick(task)}” /> 使用lambda表達試,也可以使用下面方式
    android:onClick=”@{(view) -> presenter.onSaveClick(task)}”
    兩種方式各有特點,根據自己需要來選擇。

(二)

上節我們講了基本使用,這節我們繼續講講已謝基本用法
說明:前期文章參考官方文件,因為基礎知識官方寫的很清楚。

導包

基本定義

上節我們使用了一下基礎導包,定義一個變數,如:

<variable
          name="user"
          type="com.lowett.databinding.User"/>複製程式碼

這樣寫有個問題,當有多個同樣型別的變數時候,就顯得比較麻煩了,這裡DataBinding庫提供了另一中方式
可以先導包,然後在定義變數,

<data>
       <import type="android.view.View"/>
       <!--匯入User-->
       <import type="com.lowett.databinding.User"/>

       <!--定義變數-->
       <variable
           name="user"
           type="User"
          />

       <variable
           name="listner"
           type="com.lowett.databinding.HandleClick"/>
   </data>複製程式碼

定義別名

如果類衝突,我們還可以定義別名。

<data>

       <import type="android.view.View"/>
       <!--匯入User 並定義別名-->
       <import type="com.lowett.databinding.User" alias="MyUser"/>

       <!--定義變數-->
       <variable
           name="user"
           type="MyUser"
          />

       <variable
           name="listner"
           type="com.lowett.databinding.HandleClick"/>
   </data>複製程式碼

範型定義

在Java中我們可以定義範型,在layout同樣可以,但是其中的括號需要特俗定義否則會報錯。

<data>

      <import type="java.util.List"/>
      <import type="android.view.View"/>
      <!--匯入User 並定義別名-->
      <import type="com.lowett.databinding.User" alias="MyUser"/>

      <!--定義變數-->
      <variable
          name="user"
          type="MyUser"
         />
      <!--定義範型, 如果顯示紅色沒關係可以編譯成功-->
      <variable
          name="users"
          type="List&lt;MyUser&gt;"/>

      <variable
          name="listner"
          type="com.lowett.databinding.HandleClick"/>
  </data>複製程式碼

靜態方法

匯入型別的時候我們也可匯入工具類等的靜態方法。

<data>
        <import type="com.lowett.databinding.utils.Utils"/>
</data>複製程式碼

使用:

<TextView
           android:layout_width="wrap_content"
           android:text="@{Utils.test()}"
           android:layout_height="wrap_content"/>複製程式碼

預設匯入的變數

在layout中有預設匯入幾種常用的型別,比如String,Context等,這些何以直接使用,如果顯式指定了型別將會修改掉預設的。
在layout中還有一個context變數可以直接使用。
如我們獲取螢幕尺寸:
注意:需要講int轉換為String。
這裡並沒有定義context,以及匯入String包,預設有。

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

    <data>

        <import type="com.lowett.databinding.utils.Utils"/>

    </data>

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

        <TextView
            android:layout_width="wrap_content"
            android:text="@{String.valueOf(Utils.getScreenWidth(context))}"
            android:layout_height="wrap_content"/>

    </LinearLayout>
</layout>複製程式碼

Utils.java:

public class Utils {
    public  static String test() {
        return "Test";
    }

    public static int getScreenWidth(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;
    }
}複製程式碼

自定義類名

預設的我們生成的binding類名是以佈局檔案的名字接一個Binding為字尾,我們也可以修改這個名字。
如:

<data class="MyDataClass">

  </data>複製程式碼

在佈局檔案中data節點天街class屬性並定義名字,生成MyDataClass繫結物件。位於跟包名下。
如果向指定包名,那麼寫全名即可。

<data class="com.lowett.databinding.utils.MyDataClass">

  </data>複製程式碼

這樣將會在com.lowett.databinding.utils下面生成繫結類。

參考官方文件。
未完待續

相關文章