基于Jetpack-MVVM-Best-Practice的双向绑定

227 阅读1分钟

特殊情况

复用子View的情况

在数据双向绑定中的子布局复用【已发布】

这篇文章实现的子布局复用的双向绑定,是基于原生的DataBinding

这里是基于项目:Jetpack-MVVM-Best-Practice

子布局代码

内部的EditText需要实现数据双向绑定

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="click"
            type="com.appotronics.appiot.view.listener.ClickListener" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <androidx.constraintlayout.helper.widget.Layer
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/button_group_back_combinate"
            app:constraint_referenced_ids="img_sub,edit_num,img_add" />

        <ImageView
            android:layout_width="@dimen/margin10.67dp"
            android:layout_height="13.33dp"
            android:src="@drawable/button_group_combinate_sub"
            android:scaleType="center"
            android:paddingHorizontal="2.67dp"
            android:paddingVertical="@dimen/margin6.33dp"
            android:id="@+id/img_sub"
            onClickListener="@{(v)->click.subClick(v)}"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <EditText
            android:layout_width="14.67dp"
            android:layout_height="13.33dp"
            android:id="@+id/edit_num"
            android:inputType="number"
            android:lines="1"
            android:text="@={click.editTextString}"
            tools:text="900"
            android:textSize="5.33sp"
            android:textColor="@color/white"
            android:background="@drawable/button_back_combinate"
            android:gravity="center"
            app:layout_constraintTop_toTopOf="@+id/img_sub"
            app:layout_constraintStart_toEndOf="@+id/img_sub"
            app:layout_constraintBottom_toBottomOf="@+id/img_sub" />

        <ImageView
            android:layout_width="@dimen/margin10.67dp"
            android:layout_height="13.33dp"
            android:src="@drawable/button_group_combinate_add"
            android:scaleType="center"
            android:paddingHorizontal="2.67dp"
            android:paddingVertical="@dimen/margin6.33dp"
            android:id="@+id/img_add"
            onClickListener="@{(v)->click.addClick(v)}"
            app:layout_constraintStart_toEndOf="@+id/edit_num"
            app:layout_constraintTop_toTopOf="@+id/img_sub" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

子布局绑定的类:ClickListener

editTextString是实现双向绑定的State来修饰的,和原生的LiveData是一样的,继承关系

class ClickListener{
    /**输入框内容*/
    var editTextString= State<String>("0")

    /**
     * sub点击事件
     * @param view View
     */
    fun subClick(view:View){

        var toInt = editTextString.get()?.toInt()?.minus(1)
        PrintUtil.pln("sub点击事件 $toInt")
        editTextString.set((toInt!!).toString())
    }

    /**
     * add点击事件
     * @param view View
     */
    fun addClick(view:View){

        var toInt = editTextString.get()?.toInt()?.plus(1)
        PrintUtil.pln("add点击事件 $toInt")
        editTextString.set((toInt!!).toString())
    }


}

父布局 部分代码

使用include多次引用子布局

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:bind="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="click_up_combinate"
            type="com.appotronics.appiot.view.listener.ClickListener" />

        <variable
            name="click_down_combinate"
            type="com.appotronics.appiot.view.listener.ClickListener" />

        <variable
            name="click_left_combinate"
            type="com.appotronics.appiot.view.listener.ClickListener" />

        <variable
            name="click_right_combinate"
            type="com.appotronics.appiot.view.listener.ClickListener" />

        <variable
            name="click_up_adjust"
            type="com.appotronics.appiot.view.listener.ClickListener" />

        <variable
            name="click_down_adjust"
            type="com.appotronics.appiot.view.listener.ClickListener" />

        <variable
            name="click_left_adjust"
            type="com.appotronics.appiot.view.listener.ClickListener" />

        <variable
            name="click_right_adjust"
            type="com.appotronics.appiot.view.listener.ClickListener" />

    </data>


<TextView
    android:id="@+id/tip3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/margin9.67dp"
    android:text="@string/tx_adjust_combinate_width"
    android:textColor="@color/white"
    android:textSize="@dimen/tip_6.67sp"
    app:layout_constraintStart_toStartOf="@+id/tip1"
    app:layout_constraintTop_toBottomOf="@+id/swb_subline" />

<TextView
    android:id="@+id/tip4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="5.33dp"
    android:text="@string/tx_adjust_combinate_up"
    android:textColor="@color/white"
    android:textSize="@dimen/margin5.33dp"
    app:layout_constraintBottom_toBottomOf="@+id/up_button_group"
    app:layout_constraintEnd_toStartOf="@+id/up_button_group"
    app:layout_constraintTop_toTopOf="@+id/up_button_group" />

<include
    android:id="@+id/up_button_group"
    layout="@layout/view_button_group_combinate"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="9.67dp"
    android:layout_marginEnd="18.67dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tip3"
    bind:click="@{click_up_combinate}" />

<TextView
    android:id="@+id/tip5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="5.33dp"
    android:text="@string/tx_adjust_combinate_down"
    android:textColor="@color/white"
    android:textSize="@dimen/margin5.33dp"
    app:layout_constraintBottom_toBottomOf="@+id/down_button_group"
    app:layout_constraintEnd_toStartOf="@+id/down_button_group"
    app:layout_constraintTop_toTopOf="@+id/down_button_group" />

<include
    android:id="@+id/down_button_group"
    layout="@layout/view_button_group_combinate"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="9.67dp"
    android:layout_marginEnd="18.67dp"
    bind:click="@{click_down_combinate}"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/up_button_group" />

<TextView
    android:id="@+id/tip6"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="5.33dp"
    android:text="@string/tx_adjust_combinate_left"
    android:textColor="@color/white"
    android:textSize="@dimen/margin5.33dp"
    app:layout_constraintBottom_toBottomOf="@+id/left_button_group"
    app:layout_constraintEnd_toStartOf="@+id/left_button_group"
    app:layout_constraintTop_toTopOf="@+id/left_button_group" />

<include
    android:id="@+id/left_button_group"
    layout="@layout/view_button_group_combinate"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="9.67dp"
    android:layout_marginEnd="18.67dp"
    bind:click="@{click_left_combinate}"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/down_button_group" />

<TextView
    android:id="@+id/tip7"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="5.33dp"
    android:text="@string/tx_adjust_combinate_right"
    android:textColor="@color/white"
    android:textSize="@dimen/margin5.33dp"
    app:layout_constraintBottom_toBottomOf="@+id/right_button_group"
    app:layout_constraintEnd_toStartOf="@+id/right_button_group"
    app:layout_constraintTop_toTopOf="@+id/right_button_group" />

<include
    android:id="@+id/right_button_group"
    layout="@layout/view_button_group_combinate"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="9.67dp"
    bind:click="@{click_right_combinate}"
    android:layout_marginEnd="18.67dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/left_button_group" />

GroupClickListener 包装所有之类,并拥有生命周期的监听能力

可以绑定生命周期

class GroupClickListener : StateHolder() {
    val downCombinate by lazy {
        ClickListener()
    }
    val upCombinate by lazy {
        ClickListener()
    }
    val leftCombinate by lazy {
        ClickListener()
    }
    val rightCombinate by lazy {
        ClickListener()
    }

    val downAdjust by lazy {
        ClickListener()
    }
    val upAdjust by lazy {
        ClickListener()
    }
    val leftAdjust by lazy {
        ClickListener()
    }
    val rightAdjust by lazy {
        ClickListener()
    }
}

在主页中的使用

先获取包装类
private val groupClickListener by lazy{getFragmentScopeViewModel(GroupClickListener::class.java)}

然后再逐个子类的对应过去
override fun getDataBindingConfig(): DataBindingConfig {
    initUI()
    return DataBindingConfig(
        R.layout.fragment,
        BR.vm,
        mState
    ).
        .addBindingParam(BR.click_down_combinate, groupClickListener.downCombinate)
        .addBindingParam(BR.click_up_combinate, groupClickListener.upCombinate)
        .addBindingParam(BR.click_left_combinate, groupClickListener.leftCombinate)
        .addBindingParam(BR.click_right_combinate, groupClickListener.rightCombinate)
        .addBindingParam(BR.click_right_adjust, groupClickListener.rightAdjust)
        .addBindingParam(BR.click_down_adjust, groupClickListener.downAdjust)
        .addBindingParam(BR.click_up_adjust, groupClickListener.upAdjust)
        .addBindingParam(BR.click_left_adjust, groupClickListener.leftAdjust)
}