標籤雲

搜尋此網誌

2015/11/25

Data Binding-2

繼續來探討 Data Binding 的用法

Imports
如果有使用到非 Data Object 的類別
可以使用 import 標籤

例如下例是把 visibility 設為 View.VISIBLE 或 View.GONE
就需要 import android.view.View
如果有名稱衝突可以用 alias 屬性另外取名

從以下範例可以看到 static 的屬性跟方法也都可以用
(注意範例裡面 userList 的 type 是寫成 "List<User>"
因為type裡面不允許 '<' 字符)
<data>
    <import type="android.view.View"/>
    <import type="com.example.real.estate.View"
        alias="Vista"/>
    <import type="com.example.User"/>
    <import type="java.util.List"/>
    <import type="com.example.MyStringUtils"/>

    <variable name="user" type="User"/>
    <variable name="userList" type="List&lt;User>"/>
</data>

...(省略)

<TextView
   android:text="@{user.lastName}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:visibility="@{user.isAdult?View.VISIBLE:View.GONE}"/>

<TextView
   android:text="@{((User)(user.connection)).lastName}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<TextView
   android:text="@{MyStringUtils.capitalize(user.lastName)}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
要注意的是目前 Android Studio 還無法處理 layout xml 裡的 import
所以 import 的 variables 無法有 auto complete 功能
官方建議真的想要用 auto complete 的話可以使用含 package 的完整名稱

Variables

variable type 會在 compile 時檢查是否為實作 Observable 或是 observable collection 的變數
沒有實作 Observable* interface 的變數將不會被發現

如果同一個 layout 有不同檔案(如直式跟橫式)則變數會合併
所以命名上不能有衝突

自動生成的 binding class 會給予初始值 (reference types 是 null, int 是 0, boolean 是 false...)
以避免 NullPointerException
並對每個變數產生 setter 跟 getter

<data>
    <import type="android.graphics.drawable.Drawable"/>
    <variable name="user"  type="com.example.User"/>
    <variable name="image" type="Drawable"/>
    <variable name="note"  type="String"/>
</data>

Custom Binding Class Names

binding class 的 package 是專案 package 的 databinding 下
如:com.example.my.app.databinding
其名稱已在前篇說過
但我們也可以自行指定 package 及名稱
<data class="ContactItem"> </data>
如果要在不同 package 則
<data class=".ContactItem"> </data>
或
<data class="com.example.ContactItem"> </data>

Includes

includes 的用法前篇已經示範過
不過這裡補充一點就是 include 不能作為 merge 的直接子標籤
例如以下這樣就是不支援的
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:bind="http://schemas.android.com/apk/res-auto">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <merge>
       <include layout="@layout/name"
           bind:user="@{user}"/>
       <include layout="@layout/contact"
           bind:user="@{user}"/>
   </merge>
</layout>

Expression Language

Data Binding 支援以下表達式
Mathematical+ - / * %
String concatenation+
Logical&& ||
Binary& | ^
Unary+ - ! ~
Shift>> >>> <<
Comparison== > < >= <=
instanceof
Grouping()
Literals character, String, numeric,null
Cast
Method calls
Field access
Array access [ ]
Ternary operator?:
例如這樣:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'

不過不支援 this, super, new, Explicit generic invocation(明確通用調用)

另外還支援 Null Coalescing Operator (null合併運算子),如:
android:text="@{user.displayName??user.lastName}"
//其意思等同於 android:text="@{user.displayName!=null?user.displayName:user.lastName}"

Collections

arrays, lists, sparse lists, maps 等常用的 collection 都可以用 [] operator 存取
<data>
    <import type="android.util.SparseArray"/>
    <import type="java.util.Map"/>
    <import type="java.util.List"/>
    <variable name="list" type="List&lt;String>"/>
    <variable name="sparse" type="SparseArray&lt;String>"/>
    <variable name="map" type="Map&lt;String, String>"/>
    <variable name="index" type="int"/>
    <variable name="key" type="String"/>
</data>
...(省略)
android:text="@{list[index]}"
...(省略)
android:text="@{sparse[index]}"
...(省略)
android:text="@{map[key]}"

String Literals

關於 quote 的用法
可以使用 &quot; 跟 back quote (`)
android:text='@{map["firstName"]}'
android:text="@{map[`firstName`}"
android:text="@{map[&quot;firstName&quot;]}"

Resources

Resources 的使用
格式字串和複數(@plurals/)可以通過提供參數進行評估:
android:padding="@{large?@dimen/largePadding:@dimen/smallPadding}"
android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/orange(orangeCount)}"
其結果為 Have an orange 或 Have %d oranges

如果 plurals 有多個參數,所有的參數都應該傳入:
android:text="@{@plurals/orange(orangeCount, orangeCount)}"
關於 plurals 如果不了解請參照底下相關資料 String Resources - Quantity Strings

有些資源必須要明確指定型別
請對照下表 Expression Reference
型別 Normal Reference Expression Reference
String[] @array @stringArray
int[] @array @intArray
TypedArray @array @typedArray
Animator @animator @animator
StateListAnimator @animator @stateListAnimator
color int @color @color
ColorStateList @color @colorStateList

相關資料:
Data Binding Guide
String Resources - Quantity Strings (Plurals)

沒有留言: