Android Data Binding 進階

Android Data Binding 初探
Android Data Binding 進階
Android Data Binding 配合BaseAdapter

學完 Data Binding 的基本使用方法後,我們來學學 Data Binding 的進階。

Data Binding 最大的作用就是減少我們在 Activity 寫更新和設置 UI 代碼,有時候,View的更新過程需要一些簡單的邏輯,如判斷空,拼接字段等,因此,Android 的 Data Binding 還提供了一些簡單的表達式供我們在 xml 佈局文件中使用。

例子:

數據類

public class Person extends BaseObservable {

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Bindable
    public String getName() {
        return name;
    }

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

    @Bindable
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        notifyPropertyChanged(BR.age);
    }

}

xml 佈局文件

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

    <data>
        <variable
            name="person"
            type="com.johan.study.Person" />
    </data>

    <LinearLayout xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="10dp"
        tools:context="com.johan.study.MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textSize="16dp"
            android:textColor="@android:color/holo_blue_light"
            android:text="@{person.name}"
            />

    </LinearLayout>

</layout>

Activity

public class MainActivity extends AppCompatActivity {

    private Person person = new Person(null, 25);
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setPerson(person);
    }

}

如果看不懂,請看我博客 Android Data Binding 初探

三元表達式

更新 UI 最常用的邏輯應該是三元表達式了。我們來看看在 xml 佈局文件中,三元表達式怎麼使用:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textSize="16dp"
    android:textColor="@android:color/holo_blue_light"
    android:text="@{person.name != null ? person.name : @string/app_name}"
    />

所有表達式都要寫在“@{}”裏面:

@{person.name != null ? person.name : @string/app_name}

是不是和我們在 Java 代碼寫的一樣呢?毫無違和感,爽!!

另外,在“@{}”內使用資源,也是和普通的一樣,只不過沒有提示(這點真的不太好,容易寫錯)。

三元表達式我們還能這麼用:

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

    <data>
        <!-- import 標籤的作用是引入類,和 java 代碼一樣 -->
        <!-- 因爲在@{}中使用了View類,我們必須將包引入 -->
        <import type="android.view.View" />
        <variable
            name="person"
            type="com.johan.study.Person" />
    </data>

    <LinearLayout xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="10dp"
        tools:context="com.johan.study.MainActivity">

        <!-- visibility 屬性使用了三元表達式,如果person的name爲null,就設置爲View.GONE,和 java 代碼一樣 -->
        <!-- 由於使用了 View 類,需要在data標籤引入 View 類 -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textSize="16dp"
            android:textColor="@android:color/holo_blue_light"
            android:text="@{person.name != null ? person.name : @string/app_name}"
            android:visibility="@{person.name != null ? View.VISIBLE : View.GONE}"
            />

    </LinearLayout>

</layout>

上面的例子中,如果沒有 import View 類的話,編譯器是沒有提示,你就應該想到要 import 了。

空運算符

Data Binding 還提供一個空運算符“??”

<TextView
    android:id="@+id/name_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textSize="16dp"
    android:textColor="@android:color/holo_blue_light"
    android:text="@{person.name ?? @string/app_name}"
    />

其實

@{person.name ?? @string/app_name}

就等同於

@{person.name != null ? person.name : @string/app_name}

拼接

我們可以在“@{}”內拼接字符

<TextView
    android:id="@+id/name_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textSize="16dp"
    android:textColor="@android:color/holo_blue_light"
    android:text="@{@string/app_name + person.name}"
    />

這樣就可以拼接字符了:

@{@string/app_name + person.name}

我們還能拼接“dimen”,在 dimens 資源文件定義的兩個距離

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="space_1">15dp</dimen>
    <dimen name="space_2">8dp</dimen>
</resources>

拼接 dimen 方式

<TextView
    android:id="@+id/name_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="@{@dimen/space_1 + @dimen/space_2}"
    android:textSize="16dp"
    android:textColor="@android:color/holo_blue_light"
    android:text="@{person.name}"
    />

我們看

@{@dimen/space_1 + @dimen/space_2}

這方便我們計算好距離,然後再設置,不用重新定義新距離,這個功能很有用的。

使用方法

我們在 xml 中不僅可以使用類實例的方法,還能直接使用類的靜態方法,就好像 java 一樣。

類實例方法就是我們設置的監聽事件。

我們來看看怎麼使用類的靜態方法:

定義靜態方法:

public class Utils {
    public static String formatName(String name) {
        return "姓名:" + name;
    }
}

xml 佈局文件:

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

    <data>
        <!-- import 標籤的作用是引入類,和 java 代碼一樣 -->
        <!-- 因爲在@{}中使用了Util類,我們必須將包引入 -->
        <import type="com.johan.study.Utils" />
        <variable
            name="person"
            type="com.johan.study.Person" />
    </data>

    <LinearLayout xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="10dp"
        tools:context="com.johan.study.MainActivity">

        <!-- 使用 Utils.formatName 方法 -->
        <!-- 由於使用了 Utils類,需要在data標籤引入 Utils 類 -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textSize="16dp"
            android:textColor="@android:color/holo_blue_light"
            android:text="@{Utils.formatName(person.name)}"
            />

    </LinearLayout>

</layout>

其實和我們使用 java 代碼很相似,很多東西我們不妨用 java 代碼試試!

使用數組和集合

在 xml 佈局中,我們能定義一個數組,List,Map,通過訪問下標,設置屬性值。

網上查的我都試了,不知道爲什麼 Android Studio 不支持定義數組和具體List,暫時還沒想到會用到這個,先放着吧!!(知道的,麻煩留言告知,謝謝! ^_^)

其他表達式

數學 + - / * %

字符串連接 +

邏輯 && ||

二進制 & | ^

一元運算 + - ! ~

移位 >> >>> <<

比較 == > < >= <=

instanceof

分組 ()

null

Cast

方法調用

數據訪問 []

三元運算 ?:

其他表達式自己慢慢探索,你可以的!! just try!!

include

這裏再補充一個,我們佈局的時候,可能會用到“include”標籤來複用佈局。如果“include”的 layout 也是一個 Data Binding 的佈局文件,裏面還綁定了數據,那我們怎麼賦值給“include”的 layout 的變量呢?

還是一個例子說明

layout_include.xml

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

    <data>
        <variable
            name="person"
            type="com.johan.study.Person" />
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/name_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textSize="16dp"
            android:textColor="@android:color/holo_blue_light"
            android:text="@{person.name}"
            />
    </LinearLayout>

</layout>

“include”的文件裏面定義了person變量。

activity_main.xml 佈局文件

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

    <data>
        <variable
            name="person"
            type="com.johan.study.Person" />
        <variable
            name="handler"
            type="com.johan.study.MainActivity.NameHandler" />

    </data>

    <LinearLayout xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="10dp"
        tools:context="com.johan.study.MainActivity">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:hint="輸入姓名"
            android:inputType="text"
            android:textSize="16dp"
            android:onTextChanged="@{handler.onTextChanged}"
            />

        <!-- 在 xml 文件直接傳值給 include 的 layout 中 -->
        <include
            layout="@layout/layout_include"
            binding:person="@{person}"
            />

    </LinearLayout>

</layout>

我們通過 xml 文件可以直接把值賦給“include”layout 的 person 變量中,挺方便的!!

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