El uso de DataBinding tres

I. Introducción

El uso de las expresiones registradas anteriormente DataBinding, este artículo continúa registrando el uso de objetos observables.

En segundo lugar, el campo observable

Aquí está la introducción del sitio web oficial.

La observabilidad se refiere a la capacidad de un objeto para informar a otros objetos de cambios en sus datos. Con las bibliotecas de enlace de datos, puede hacer observables objetos, campos o colecciones.

Se puede usar cualquier objeto simple para el enlace de datos, pero la modificación del objeto no actualiza automáticamente la interfaz. Con el enlace de datos, los objetos de datos pueden notificar a otros objetos, u oyentes, cuando cambien sus datos. Hay tres tipos diferentes de clases observables: objetos , campos y colecciones .

Cuando uno de los objetos de datos observables está vinculado a la interfaz y las propiedades de ese objeto de datos cambian, la interfaz se actualiza automáticamente.

Aquí hay un ejemplo para ilustrar el papel de la observabilidad. Veamos primero el código que no usa campos observables. Aquí, las clases ordinarias se usan para el enlace de datos para mostrar contenido.

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:bind="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="change"
            type="String" />
    </data>

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

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/update_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="@{change}"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            tools:text="value" />

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

MainActivity.kt

class MainActivity : AppCompatActivity() {
    
    
    private var changeValue = "你好啊"
    private val binding: ActivityMainBinding by lazy {
    
    
        ActivityMainBinding.inflate(layoutInflater)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        binding.change = changeValue
        changeValue = "我不好"
    }
}

El código primero xmlse vincula con la cadena sum y luego cambia la cadena más tarde. El resultado es de esperar, el contenido modificado más tarde no se mostrará en el diseño de la interfaz de usuario, lo cual es un fenómeno normal. Pero en el proyecto, suponiendo que este campo deba cambiarse muchas veces, binding.change = changeValueserá muy engorroso volver a ejecutarlo cada vez después de la asignación. Entonces, la función de campo observable se introduce aquí, veamos el código modificado a continuación.

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:bind="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="change"
            type="androidx.databinding.ObservableField<String>" />

    </data>

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

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/update_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="@{change}"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            tools:text="value" />


        <androidx.appcompat.widget.AppCompatEditText
            android:id="@+id/input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@+id/update_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"/>

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="@{input.text}"
            app:layout_constraintTop_toBottomOf="@+id/input"
            app:layout_constraintStart_toStartOf="parent" />


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

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private val changeValue = ObservableField<String>("你好啊")
    private val binding: ActivityMainBinding by lazy {
        ActivityMainBinding.inflate(layoutInflater)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        binding.change = changeValue
        changeValue.set("我不好")
    }
}

De esta manera, la interfaz de usuario se puede cambiar en tiempo real cuando se cambia el contenido de la cadena.

DataBindingLos campos observables básicos proporcionados en son los siguientes

Hay algo de trabajo por hacer cuando se crea una clase que implementa la Observableinterfaz , pero no tiene mucho sentido si su clase tiene solo unas pocas propiedades. En este caso, puede usar la Observableclase y las siguientes clases específicas de primitivas para hacer que el campo sea observable:

Por ejemplo, si creamos una nueva clase para almacenar información del usuario, podemos completar las variables observables.

    class User {
    
    
        val firstName = ObservableField<String>()
        val lastName = ObservableField<String>()
        val age = ObservableInt()
    }

3. Colección observable

Además de los campos observables, también hay colecciones observables, principalmente ObservableArrayMapyObservableArrayList

    ObservableArrayMap<String, Any>().apply {
    
    
        put("firstName", "Google")
        put("lastName", "Inc.")
        put("age", 17)
    }

    ObservableArrayList<Any>().apply {
    
    
        add("Google")
        add("Inc.")
        add(17)
    }
<data>
        <import type="android.databinding.ObservableMap"/>
        <variable name="user" type="ObservableMap<String, Object>"/>

        <import type="android.databinding.ObservableList"/>
        <import type="com.example.my.app.Fields"/>
        <variable name="user2" type="ObservableList<Object>"/>
    </data><TextView
        android:text="@{user.lastName}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:text="@{String.valueOf(1 + (Integer)user.age)}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

     <TextView
        android:text='@{user2[Fields.LAST_NAME]}'
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:text='@{String.valueOf(1 + (Integer)user2[Fields.AGE])}'
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

4. Objetos observables

A veces, el método proporcionado oficialmente no puede satisfacer las necesidades y debe expandirse por sí mismo. En este momento, se puede implementar Observablepara completar esta función.

    class User : BaseObservable() {
    
    

        @get:Bindable
        var firstName: String = ""
            set(value) {
    
    
                field = value
                notifyPropertyChanged(BR.firstName)
            }

        @get:Bindable
        var lastName: String = ""
            set(value) {
    
    
                field = value
                notifyPropertyChanged(BR.lastName)
            }
    }
    

Lo siguiente se cita de la documentación oficial.

El enlace de datos genera BRuna que contiene el ID del recurso utilizado para el enlace de datos. Durante la compilación, Bindablelas anotaciones generan una entrada en el archivo de BRclase . Si la clase base de la clase de datos no se puede cambiar, la Observableinterfaz se puede implementar usando un PropertyChangeRegistryobjeto para registrar y notificar a los oyentes de manera efectiva.

Cómo implementar Observablela interfaz

class User : Observable {
    
    

    private val property : PropertyChangeRegistry by lazy {
    
    //默认是线程安全的
        PropertyChangeRegistry()
    }

    @get:Bindable
    var change: String = ""
        set(value) {
    
    
            field = value
            notifyPropertyChanged(BR.change)
        }

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

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

    fun notifyChange(){
    
    
        property.notifyCallbacks(this, 0, null)
    }
    fun notifyPropertyChanged(fieldId : Int) {
    
    
        property.notifyCallbacks(this, fieldId, null);
    }
}

5. Enlaces de referencia

  1. Uso de objetos de datos observables | Desarrolladores de Android | Desarrolladores de Android

Supongo que te gusta

Origin blog.csdn.net/Mr_Tony/article/details/124255550
Recomendado
Clasificación