1. 程式人生 > >Data Binding Component詳解

Data Binding Component詳解

上一篇從零開始的Android新專案8 - Data Binding高階篇中,我們提到了使用Component來進行注入,以方便進行測試的功能,有一些朋友說寫的不夠清楚,還有些疑惑,所以本篇就來詳細說說Component。

作為例子,我們的實現目標是使用Data Binding Component,讓應用全域性的TextView的文字都能隨時變成test,還能進行全域性換膚。

DataBindingComponent介面

build/intermediates/classes下面,可以找到DataBindingComponent類,包名為android.databinding,全域性只會有一個該類——此介面在編譯時生成,包含了所有用到的例項BindingAdapters的getter方法。

當一個BindingAdapter是一個例項方法(instance method),一個實現該方法的類的例項必須被例項化。這個生成的介面會包含每個宣告BindingAdapter的類/介面的get方法。命名衝突會簡單地加一個數字字首到get方法前來解決。

如果使用Dagger 2,開發者可以繼承這個介面,並把繼承的介面註解為Component。

第一個介面全域性起作用,後兩個介面僅對該語句inflate的佈局起作用。

建立Component

宣告抽象adapter

如果不需要實現多個Component,可以直接跳過這一步。

我們宣告一個抽象的adapter,在其中寫上抽象方法來設定我們想要做data binding的屬性,這裡我們直接幹掉了TextView的android名稱空間下的text和textColor兩個屬性。

這裡的@BindingAdapter註解會讓data binding在component中生成我們這個adapter的get方法(必須是非靜態的)。

public abstract class MyBindingAdapter {

    @BindingAdapter("android:text")
    public abstract void setText(TextView view, String value);

    @BindingAdapter("android:textColor")
    public abstract void setTextColor
(TextView view, int value); }

實現adapter

我們繼承MyBindingAdapter分別實現兩個adapter:

ProductionBindingAdapter.java:

public class ProductionBindingAdapter extends MyBindingAdapter {

    @Override
    public void setText(TextView view, String value) {
        TextViewBindingAdapter.setText(view, value);
    }

    @Override
    public void setTextColor(TextView view, int value) {
        view.setTextColor(value);
    }
}

TestBindingAdapter.java:

public class TestBindingAdapter extends MyBindingAdapter {

    @Override
    public void setText(TextView view, String value) {
        view.setText(value + " test");
    }

    @Override
    public void setTextColor(TextView view, int value) {
        if (value == view.getContext()
                .getResources()
                .getColor(R.color.textColorDay)) {
            view.setTextColor(view.getContext()
                    .getResources()
                    .getColor(R.color.textColorNight));
        }
    }
}

前者使用的是原來的設定,後者則分別給text加上了” test”字尾,並做了color的轉換,實現了字型顏色的“換膚”功能。

實現component

在寫了上面的程式碼後,再看看DataBindingComponent,會發現裡面多了一個介面方法,遂實現之:

生產環境Component:

public class ProductionComponent implements DataBindingComponent {

    private MyBindingAdapter mAdapter = new ProductionBindingAdapter();

    @Override
    public MyBindingAdapter getMyBindingAdapter() {
        return mAdapter;
    }
}

測試環境Component:

public class TestComponent implements DataBindingComponent {

    private MyBindingAdapter mAdapter = new TestBindingAdapter();

    @Override
    public MyBindingAdapter getMyBindingAdapter() {
        return mAdapter;
    }
}

使用

layout

原先的text和textColor屬性並沒有通過data binding設定,我們要給它們套上@{}:

<Button
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:onClick="@{presenter.onClickSimpleDemo}"
    android:text="@{@string/demo_simple}"
    android:textColor="@{@color/textColorDay}"/>

注入component

注入Component很簡單,我們做全域性的注入只需要呼叫:

if (DemoApplication.isTest) {
    DataBindingUtil.setDefaultComponent(new ProductionComponent());
} else {
    DataBindingUtil.setDefaultComponent(new TestComponent());
}

重新建立activity

由於點選事件在MainActivity建立後才觸發,所以這個activity上並不會起作用,我們需要重新建立它:

public void onClickInjectDemo(View view) {
    if (DemoApplication.isTest) {
        DataBindingUtil.setDefaultComponent(new ProductionComponent());
    } else {
        DataBindingUtil.setDefaultComponent(new TestComponent());
    }
    DemoApplication.isTest = !DemoApplication.isTest;
    recreate();
}

設定後recreate()即可。可以看demo工程的效果,點選最後的按鈕後,字型顏色發生變化,textview的text後面都加上了test字串。

靜態adapter方法

那麼靜態的BindingAdapter方法怎麼去和Component做關聯呢?很簡單,只需要作為方法的第一個引數就可以了:

@BindingAdapter("android:src")
public static void loadImage(TestComponent component,
                             ImageView view, String url) {
    /// ...
}

本篇我們實踐了Data Binding中比較高階的特性:Component。

其使用場景很多,如:
- 換膚
- 打點
- 替換原生屬性
- 等等

歡迎大家發揮自己的想象力,補充更多的使用場景。