一看就會 Android框架DataBinding的使用與封裝

語言: CN / TW / HK

theme: juejin highlight: a11y-dark


本文已參與「新人創作禮」活動,一起開啟掘金創作之路。

Android中DataBinding的封裝

先簡單的介紹DataBinding

DataBinding 是谷歌官方發佈的一個框架,是 MVVM 模式在 Android 上的一種實現,減少了佈局和邏輯的耦合,數據能夠單向或雙向綁定到 layout 文件中,有助於防止內存泄漏,而且能自動進行空檢測以避免空指針異常。

雖然現在Xml中可以寫邏輯代碼了,但是還是推薦不要直接在xml裏面寫複雜的邏輯,如果有必要的需求,我們可以用BindingAdapter 自定義屬性。

話不多説,快來看看怎麼用!

一. 如何使用

1.1.數據的綁定

gradle開啟功能, 4.0以上和以下的有區別。現在很少有4.0以下的吧。 ```js android { viewBinding { enabled = true } dataBinding{ enabled = true } }

// Android Studio 4.0 android { buildFeatures { dataBinding = true viewBinding = true } } 開啟DataBinding之後,xml會默認編譯為Java對象,如果不想自己的非DB的xml被編譯,可以在xml添加忽略js tools:viewBindingIgnore="true" ```
正常的xml中需要用layout佈局包裹,模板如下:

```xml

<data>

    <variable
        name="testBean"
        type="com.guadou.kt_demo.demo.demo12_databinding_texing.TestBindingBean" />

    <variable
        name="click"
        type="com.guadou.kt_demo.demo.demo12_databinding_texing.Demo12Activity.ClickProxy" />

</data>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:orientation="vertical">

     <!--    注意雙向綁定的寫法    -->
       <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@={click.etLiveData}" />

       <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="綁定(獲取值)"
            binding:clicks="@{click.showETText}" />

     <include
        layout="@layout/include_databinding_test"
        binding:click="@{click}"
        binding:testBean="@{testBean}" />

     <com.guadou.kt_demo.demo.demo12_databinding_texing.CustomTestView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        binding:clickProxy="@{click}"
        binding:testBean="@{testBean}" />

</LinearLayout>

```


xml中data閉包是數據源,我們定義了類型之後需要在Activity/Fragment中設置,例如:

kotlin val view = CommUtils.inflate(R.layou.include_databinding_test) //綁定DataBinding 並賦值自定義的數據 DataBindingUtil.bind<IncludeDatabindingTestBinding>(view)?.apply { testBean = TestBindingBean("haha", "heihei", "huhu") click = clickProxy }

綁定數據的類型我們可以用LiveData或Flow都可以: kotlin val etLiveData: MutableLiveData<String> = MutableLiveData() val etFlow: MutableStateFlow<String?> = MutableStateFlow(null) 直接XML中雙向綁定數據或者單向的綁定數據即可 ```xml

```

1.2 佈局的綁定

inflate/include/ViewStub/CustomView如何綁定佈局與DataBinding

include/ViewStub這樣用: xml <include layout="@layout/include_databinding_test" binding:click="@{click}" binding:testBean="@{testBean}" /> include_databinding_test: ```xml

<data>

    <variable
        name="testBean"
        type="com.guadou.kt_demo.demo.demo12_databinding_texing.TestBindingBean" />

    <variable
        name="click"
        type="com.guadou.kt_demo.demo.demo12_databinding_texing.Demo12Activity.ClickProxy" />

    <import
        alias="textUtlis"
        type="android.text.TextUtils" />
</data>

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

    <TextView
        android:layout_marginTop="15dp"
        android:text="下面是賦值的數據"
        binding:clicks="@{click.testToast}"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{testBean.text1}" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{testBean.text2}" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{testBean.text3}" />

</LinearLayout>

include:kotlin //Activity中動態的加載佈局 fun inflateXml() { //給靜態的xml,賦值數據,賦值完成之後 include的佈局也可以自動顯示 mBinding.testBean = TestBindingBean("haha", "heihei", "huhu")

        //獲取View
        val view = CommUtils.inflate(R.layout.include_databinding_test)
        //綁定DataBinding 並賦值自定義的數據
        DataBindingUtil.bind<IncludeDatabindingTestBinding>(view)?.apply {
            testBean = TestBindingBean("haha1", "heihei1", "huhu1")
            click = clickProxy
        }
        //添加布局
        mBinding.flContent.apply {
            removeAllViews()
            addView(view)
        }
    }

自定義View,在Xml中定義和在Activity中手動定義是一樣的。這裏演示手動定義賦值:kotlin fun customView() { //給靜態的xml,賦值數據,賦值完成之後 include的佈局也可以自動顯示 mBinding.testBean = TestBindingBean("haha2", "heihei2", "huhu2")

        //動態的添加自定義View
        val customTestView = CustomTestView(mActivity)
        customTestView.setClickProxy(clickProxy)
        customTestView.setTestBean(TestBindingBean("haha3", "heihei3", "huhu3"))

        mBinding.flContent2.apply {
            removeAllViews()
            addView(customTestView)
        }
    }

``` 自定義Viewr中綁定屬性:

```xml class CustomTestView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : LinearLayout(context, attrs, defStyleAttr) {

init {
    orientation = VERTICAL

    //傳統的方式添加
    val view = CommUtils.inflate(R.layout.layout_custom_databinding_test)
    addView(view)

}

//設置屬性
fun setTestBean(bean: TestBindingBean?) {

    bean?.let {
        findViewById<TextView>(R.id.tv_custom_test1).text = it.text1
        findViewById<TextView>(R.id.tv_custom_test2).text = it.text2
        findViewById<TextView>(R.id.tv_custom_test3).text = it.text3
    }

}

fun setClickProxy(click: Demo12Activity.ClickProxy?) {
    findViewById<TextView>(R.id.tv_custom_test1).click {
        click?.testToast()
    }
}

} ```

1.3 事件的綁定

比較常見的是Click和控件的事件監聽回調:

xml <EditText android:id="@+id/et_redpack_money" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/d_9dp" android:layout_weight="1" android:background="@null" android:hint="0.00" android:inputType="numberDecimal" android:paddingLeft="@dimen/d_9dp" android:singleLine="true" android:textColor="@color/black_33" android:textCursorDrawable="@null" android:textSize="@dimen/d_25sp" binding:typefaceSemiBold="@{true}" binding:onTextChanged="@{click.onAmountChanged}" binding:setDecimalPoints="@{2}" /> Click封裝的代碼中使用高階函數來接收回調 ```kotlin inner class ClickProxy {

    //金額變化
    val onAmountChanged: (String) -> Unit = {
        calculationTotalAmount(it)
    }
   ...
}

**點擊事件的封裝:** 注意一個是我的封裝clicks,一個是遠程android的屬性clickxml

「其他文章」