1. 程式人生 > >DataBinding 學習系列(2)詳解DataBinding在xml中的使用

DataBinding 學習系列(2)詳解DataBinding在xml中的使用

前言

上一篇簡單的介紹了DataBinding的用法,這幾篇來仔細的介紹一下的功能。

data 標籤 的功能

<data class="test"></data>

class 屬性

生成指定的名稱的Binding物件。

什麼是Bind物件呢?來回顧之前的一句程式碼

ViewDataBinding mBinder = DataBindingUtil.setContentView(this, R.layout.activity_main);

通過這一句,系統會自動幫助我們生成一個ViewDataBinding的子類,幫助我們操作xml中繫結的資料,所以就需要給這個類起一個響亮的名字,根據Java的命名規則,R.layout.activity_main 就會預設生成 ActivityMainBinding,這個規則一看就明白。

class屬性就是幫助我們改變生成的類名和位置,有以下三種用法:

1、在模組封裝包的databinding包中會生成名為TestBinding的Binding類。

<data class="TestBinding"></data>

2、在這個情況下,TestBinding類直接在模組包種生成

<data class="TestBinding"></data>

3、在指定的包下生成Binding類。

<data class="com.example.TestBinding"></data>

如果沒有特殊需求,使用系統預設的命名就可以了。

那生成的ActivityMainBinding 與 ViewDataBinding 之間有什麼區別呢??
最大的區別的就在於ActivityMainBinding中為設定的variable生成了setter 和 getter方法,設定繫結資料更加簡便。

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding mBinder;

    private User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super
.onCreate(savedInstanceState); mBinder = DataBindingUtil.setContentView(this, R.layout.activity_main); // 設定繫結的user物件 user = new User(); user.setName("屌爆了"); mBinder.setUser(user); // 繫結listener物件 TestClickListener testClickListener = new TestClickListener(); mBinder.setListener(testClickListener); } /** * 自定義的點選回撥監聽 **/ public class TestClickListener { public void onClickListenerBinding(View view) { Toast.makeText(MainActivity.this, "1111", Toast.LENGTH_SHORT).show(); } }

data 的子標籤

variable

這個標籤之前已經見過了,他用來繫結具體的物件的類。

<variable
    name="user"
    type="com.lzp.myapplication.bean.User"/>

import

<data>
    <import type="java.util.List"/>
    <variable name="users" type="List&lt;String&gt;" />
    <import type="com.example.util.StringUtil"/>
</data>

請注意,在xml中對於尖括號(<>)的使用是很嚴格的,否則會影響xml的正常解析,所以在這裡必須對尖括號進行轉義,雖然會紅字報錯,但是是可以正常執行的。

import 表示引入引入某一個類,從上面看到引入了java.util.List,然後定了User的列表,還有引入了一個工具類 com.example.util.StringUtil。

name 是引用的名稱, type是具體的包名+類名,指明具體的類的地址。

那麼如果引入了兩個相同類名的怎麼辦?

<data>

    <import
        type="com.lzp.myapplication.bean.User" />

    <import
        type="com.lzp.myapplication.User"
        alias="User2" />

</data>

import 還有一個alias屬性,幫助我們來為引入的物件起別名,同樣可以引用,這樣就可以區別相同類名的不同類了。

如何使用data中引入和定義的內容

variable

使用variable中的bean物件,如果是屬性,直接使用@{name.field}

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

如果使用的無引數方法,@{() -> name.function()}

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{() -> listener.onClickListenerBinding()}"
            android:text="@{Utility.autoAppend(v,user.name)}" />

點選事件需要把點選的view傳入並操作,@{(v) -> name.function(v)}

括號中間的v就表示當前的這個view的引數名稱(可以自定義),直接作為引數名使用就可以。

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{(v) -> listener.onClickListenerBinding(v)}"
            android:text="@{user.name}" />

import

使用import引入的工具類,@{util.function()}

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{Utility.autoAppend(user.name)}" />

目前在靜態方法不能通過使用bean的形式來傳入view引數,具體解決辦法之後在介紹。

include

Includes的使用

<?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>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <include layout="@layout/name"
           bind:user="@{user}"/>
       <include layout="@layout/contact"
           bind:user="@{user}"/>
   </LinearLayout>
</layout>

系統會自動生成一個自定義屬性bind,通過bind可以直接對include中的layout中繫結的資料直接進行賦值,這樣就可以間接的控制include中的操作。

ViewStub

如果是ViewStub怎麼繫結??

binding = DataBindingUtil.setContentView(this, R.layout.activity_view_stub);
binding.viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {
    @Override
    public void onInflate(ViewStub stub, View inflated) {
        ViewStubBinding binding = DataBindingUtil.bind(inflated);
        User user = new User("fee", "lang");
        binding.setUser(user);
    }
});

分析上面的程式碼,首先ViewStub在尚未新增到xml中時,獲取Bindgin物件肯定是無效的,所以需要在OnInflateListener中回撥被新增的事件,然後再去獲Bing物件。

總結

我們已經把DataBinding的大部分使用場景都已經講過了,已經能夠滿足大部分場景的需求,從一個小白直接飆升到了中級水平,但是勤能補拙,熟能生巧,我們還需要通過不懈的練習來鞏固所學的知識。有講錯的地方和不足請留言指出,大家一起學習進步。

下一篇我們來了解一下DataBinding 在 Java 程式碼為我們具體提供了哪些重大的功能。