一看就會 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

「其他文章」