安卓dataBinding双向绑定

564 阅读1分钟

1.app/build.gradle文件中android节点内启用dataBinding

buildFeatures {
        dataBinding = true
    }

2.app/build.gradle添加依赖

implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"

3.ObservableViewModel

/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yuefeng.fff

import androidx.lifecycle.ViewModel
import androidx.databinding.Bindable
import androidx.databinding.Observable
import androidx.databinding.PropertyChangeRegistry

/**
 * An [Observable] [ViewModel] for Data Binding.
 */
open class ObservableViewModel : ViewModel(), Observable {

    private val callbacks: PropertyChangeRegistry by lazy { PropertyChangeRegistry() }

    override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) {
        callbacks.add(callback)
    }

    override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) {
        callbacks.remove(callback)
    }

    /**
     * Notifies listeners that all properties of this instance have changed.
     */
    @Suppress("unused")
    fun notifyChange() {
            callbacks.notifyCallbacks(this, 0, null)
    }

    /**
     * Notifies listeners that a specific property has changed. The getter for the property
     * that changes should be marked with [Bindable] to generate a field in
     * `BR` to be used as `fieldId`.
     *
     * @param fieldId The generated BR id for the Bindable field.
     */
    fun notifyPropertyChanged(fieldId: Int) {
        callbacks.notifyCallbacks(this, fieldId, null)
    }
}

4.viewmodel:MainActivity,MainVM

package com.yuefeng.fff

import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.Observable
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.yuefeng.fff.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private val vm by lazy {
        ViewModelProvider(this)[MainVM::class.java]
    }
    private val binding: ActivityMainBinding by lazy {
        DataBindingUtil.setContentView(this, R.layout.activity_main)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
        binding.vm = vm
        binding.lifecycleOwner = this
        vm.getdata()

        binding.button.setOnClickListener {
            vm.getdata1()
        }

        vm.error.observe(this, Observer {
            Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
        })

        vm.success.observe(this, Observer { it ->
            when (it) {
                Method.M1 -> {
                    Toast.makeText(this, "m1", Toast.LENGTH_SHORT).show()
                }
                Method.M2 -> {
                    Toast.makeText(this, "m2", Toast.LENGTH_SHORT).show()
                }
            }
        })
    }
}
package com.yuefeng.fff

import android.util.Log
import androidx.databinding.Bindable
import androidx.lifecycle.MutableLiveData

class MainVM : ObservableViewModel() {

    val success by lazy { MutableLiveData<Int>() }
    val error by lazy { MutableLiveData<String>() }
    var hello: Pgycheck = Pgycheck()

    //@Bindable写在实体类中就好,这里其实可以不这么写
    var buildBuildVersion: String = ""
        @Bindable get
        set(value) {
            field = value
            notifyPropertyChanged(BR.buildBuildVersion)
        }

    fun getdata() {
        success.value=Method.M1
        buildBuildVersion = "发发发"
    }

    fun getdata1() {
        success.value=Method.M2
        hello.data.buildBuildVersion = "好看" + "haohao"
        Log.i("result-->", hello.data.buildBuildVersion)
//        error.value = "回调啦啦啦"
    }
}

5.model:Pgycheck

package com.yuefeng.fff

import android.util.Log
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import java.io.Serializable

data class Pgycheck(
    var code: Int = 0,
    var message: String = "",
    var `data`: Data = Data(),
) : BaseObservable(), Serializable {
    data class Data(
//        var buildBuildVersion: String = "",
        var forceUpdateVersion: String = "",
        var forceUpdateVersionNo: String = "",
        var needForceUpdate: Boolean = false,
        var downloadURL: String = "",
        var buildHaveNewVersion: Boolean = false,
        var buildVersionNo: String = "",
        var buildVersion: String = "",
        var buildShortcutUrl: String = "",
        var buildUpdateDescription: String = "",
    ) : BaseObservable() {
        var buildBuildVersion: String = ""
            @Bindable get
            set(value) {
                field = value
                Log.i("result-->","触发set方法啦")
                notifyPropertyChanged(BR.buildBuildVersion)
            }
    }
}

6.view:activity_main.xml

<?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:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="vm"
            type="com.yuefeng.fff.MainVM" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={vm.hello.data.buildBuildVersion}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="113dp"
            android:text="Button"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="79dp"
            android:text="@={vm.buildBuildVersion}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/button" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>