当前位置:网站首页>Jetpack's dataBinding

Jetpack's dataBinding

2022-08-11 06:34:00 The rest of my life love static

一、概览

数据绑定库(dataBinding)是一种支持库,借助该库,您可以使用Declarative format(而非程序化地)将布局中的界面组件绑定到应用中的数据源.

二、使用入门

要将应用配置为使用数据绑定,请在应用模块的 build.gradle 文件中添加 dataBinding 元素

 dataBinding {
        enabled = true
    }

三、布局和绑定表达式

数据绑定布局文件略有不同,以根标记 layout开头,后跟 data 元素和 view 根元素.此视图元素是非绑定布局文件中的根.
User

data class User(val firstName: String, val lastName: String) {
    var like: Int = 0
}

activity_normal

<?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="user"
          type="com.anniljing.jetpackviewmodel.model.User" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".activity.NormalActivity">
      <TextView
          android:id="@+id/normalName"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          app:layout_constraintLeft_toLeftOf="parent"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintRight_toRightOf="parent"
          app:layout_constraintBottom_toBottomOf="parent"/>
        <TextView
            android:id="@+id/normalLike"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toRightOf="@id/normalName"
            app:layout_constraintTop_toTopOf="@id/normalName"
            android:text="@{Integer.toString(user.like)}"
            android:layout_marginLeft="20dp"/>
        <Button
            android:id="@+id/addLikeBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="@id/normalName"
            app:layout_constraintTop_toBottomOf="@id/normalName"
            android:text="Like"
            android:onClick="addLike"/>
        <TextView
            android:id="@+id/currentLike"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="@id/addLikeBtn"
            app:layout_constraintTop_toBottomOf="@id/addLikeBtn"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

data标签

dataThere are two types of sub-tabs below the tab:importvariable,variable 标签为变量,Similar to how we defined a variable,name 为变量名,type Fully qualified type name for the variable,包括包名.布局中通过 @{} to refer to the value of this variable,{} can be any Java 表达式;

 <variable
          name="user"
          type="com.anniljing.jetpackviewmodel.model.User" />

同样,我们还可以使用import来定义变量

      <import
            alias="User"
            type="com.anniljing.jetpackviewmodel.model.User" />

        <variable
            name="user"
            type="User" />

NormalActivity

class NormalActivity : AppCompatActivity() {
    private var binding:ActivityNormalBinding ?=null
    private val user=User("张三","李四")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding=DataBindingUtil.setContentView(this,R.layout.activity_normal)
        user.like=1
        binding!!.user=user
    }

    fun addLike(view: View) {
         user.like=user.like+1
         binding!!.currentLike.text="Current likes:"+user.like
    }
}

在这里插入图片描述
上面截图可以看出,No matter how you increase the number of likes,will not be timely“更新”到UI上,Is there any solution to achieve dynamic updateUI呢?答案是肯定的,使用可观察的数据对象.

使用可观察的数据对象

可观察性是指一个对象将其数据变化告知其他对象的能力.通过数据绑定库,您可以让对象、字段或集合变为可观察.当其中一个可观察数据对象绑定到界面并且该数据对象的属性发生更改时,界面会自动更新.

可观察字段

在创建实现 Observable 接口的类时要完成一些操作,但如果您的类只有少数几个属性,这样操作的意义不大.在这种情况下,您可以使用通用 Observable 类和以下特定于基元的类,将字段设为可观察字段:

  • ObservableBoolean
  • ObservableBoolean
  • ObservableByte
  • ObservableChar
  • ObservableShort
  • ObservableInt
  • ObservableLong
  • ObservableFloat
  • ObservableDouble
  • ObservableParcelable

ObservableUser

package com.anniljing.jetpackviewmodel.model

import androidx.databinding.ObservableInt

data class ObservableUser(val firstName:String, val like:ObservableInt)

activity_observable_normal

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

    <data>

        <variable
            name="user"
            type="com.anniljing.jetpackviewmodel.model.ObservableUser" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:id="@+id/normalLike"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:text="@{Integer.toString(user.like)}"/>

        <Button
            android:id="@+id/addLikeBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="addLike"
            android:text="Like" />

        <TextView
            android:id="@+id/currentLike"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</layout>

ObservableNormalActivity

package com.anniljing.jetpackviewmodel.activity

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableInt
import com.anniljing.jetpackviewmodel.R
import com.anniljing.jetpackviewmodel.databinding.ActivityObservableNormalBinding
import com.anniljing.jetpackviewmodel.model.ObservableUser

class ObservableNormalActivity : AppCompatActivity() {
    private lateinit var binding: ActivityObservableNormalBinding
    private val observableUser = ObservableUser("张三", ObservableInt(0))
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding =
            DataBindingUtil.setContentView(this, R.layout.activity_observable_normal)
        binding.user = observableUser
    }

    fun addLike(view: View) {
        observableUser.like.set(observableUser.like.get() + 1)
        binding!!.currentLike.text = "Current likes:" + observableUser.like.get()
    }
}

在这里插入图片描述

可观察对象

实现 Observable 接口The class allows to register listeners,以便它们接收有关可观察对象的属性更改的通知.Observable 接口具有添加和移除监听器的机制,但何时发送通知必须由您决定.为便于开发,数据绑定库提供了用于实现监听器注册机制的 BaseObservable 类.实现 BaseObservable 的数据类负责在属性更改时发出通知.具体操作过程是向 getter 分配 Bindable 注释,然后在 setter 中调用 notifyPropertyChanged() 方法

CustomObservableUser

package com.anniljing.jetpackviewmodel.model

import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import androidx.databinding.library.baseAdapters.BR


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

    @get:Bindable
    var like: Int = 0
        set(value) {
            field = value
            notifyPropertyChanged(BR.like)
        }
}

PS:
1、要导入androidx.databinding.library.baseAdapters.BR
2、如果在notifyPropertyChangedcannot be included in the parametersBRwhen pointing to an attribute,可以执行android studio工具栏build---->make progect

activity_observable_custom

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

    <data>

        <variable
            name="user"
            type="com.anniljing.jetpackviewmodel.model.CustomObservableUser" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center">
        <TextView
            android:id="@+id/normalLike"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:text="@{Integer.toString(user.like)}"/>

        <Button
            android:id="@+id/addLikeBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="addLike"
            android:text="Like" />

        <TextView
            android:id="@+id/currentLike"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</layout>

ObservableCustomActivity

package com.anniljing.jetpackviewmodel.activity

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableInt
import com.anniljing.jetpackviewmodel.R
import com.anniljing.jetpackviewmodel.databinding.ActivityObservableCustomBinding
import com.anniljing.jetpackviewmodel.databinding.ActivityObservableNormalBinding
import com.anniljing.jetpackviewmodel.model.CustomObservableUser
import com.anniljing.jetpackviewmodel.model.ObservableUser

class ObservableCustomActivity : AppCompatActivity() {
    private lateinit var binding: ActivityObservableCustomBinding
    private val observableUser = CustomObservableUser()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding =
            DataBindingUtil.setContentView(this, R.layout.activity_observable_custom)
        binding.user = observableUser
    }

    fun addLike(view: View) {
        observableUser.like=observableUser.like+ 1
        binding!!.currentLike.text = "Current likes:" + observableUser.like
    }
}

在这里插入图片描述

四、绑定适配器

The binding adapter is responsible for issuing the corresponding framework calls设置值.例如,设置属性值就像调用 setText() 方法一样.再比如,设置事件监听器就像调用 setOnClickListener() 方法.
数据绑定库允许您通过使用适配器指定为设置值而调用的方法、提供您自己的绑定逻辑,以及指定返回对象的类型.

指定自定义方法名称

一些Properties have names that do not match setter 方法.在这些情况下,某个特性可能会使用 BindingMethods 注释与 setter 相关联.注释与类一起使用,可以包含多个 BindingMethod 注释,每个注释对应一个重命名的方法.绑定方法是可添加到应用中任何类的注释.在以下示例中,android:tint 属性与 setImageTintList(ColorStateList) 方法相关联,而不与 setTint() 方法相关联

 /**
     * Applies a tint to the image drawable. Does not modify the current tint
     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
     * <p>
     * Subsequent calls to {@link #setImageDrawable(Drawable)} will automatically
     * mutate the drawable and apply the specified tint and tint mode using
     * {@link Drawable#setTintList(ColorStateList)}.
     * <p>
     * <em>Note:</em> The default tint mode used by this setter is NOT
     * consistent with the default tint mode used by the
     * {@link android.R.styleable#ImageView_tint android:tint}
     * attribute. If the {@code android:tint} attribute is specified, the
     * default tint mode will be set to {@link PorterDuff.Mode#SRC_ATOP} to
     * ensure consistency with earlier versions of the platform.
     *
     * @param tint the tint to apply, may be {@code null} to clear tint
     *
     * @attr ref android.R.styleable#ImageView_tint
     * @see #getImageTintList()
     * @see Drawable#setTintList(ColorStateList)
     */
    @android.view.RemotableViewMethod
    public void setImageTintList(@Nullable ColorStateList tint) {
        mDrawableTintList = tint;
        mHasDrawableTint = true;

        applyImageTint();
    }

BindingTintMethods

package com.anniljing.jetpackviewmodel.util

import android.widget.ImageView
import androidx.databinding.BindingMethod
import androidx.databinding.BindingMethods

@BindingMethods(value = [
    BindingMethod(
        type = ImageView::class,
        attribute = "tint",
        method = "setImageTintList")])
class BindingTintMethods {
}

activity_observable_binding_methods

<?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">

    <data>
        <variable
            name="user"
            type="com.anniljing.jetpackviewmodel.model.ObservableUser" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{Integer.toString(user.like)}"/>
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_whatshot_black_96dp"
            app:tint="@{user.like > 9 ? @color/star : @android:color/black}" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Like"
            android:onClick="addLike"/>
    </LinearLayout>
</layout>

ObservableBindingMethodsActivity

package com.anniljing.jetpackviewmodel.activity

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableInt
import com.anniljing.jetpackviewmodel.R
import com.anniljing.jetpackviewmodel.databinding.ActivityObservableBindingMethodsBinding
import com.anniljing.jetpackviewmodel.model.ObservableUser

class ObservableBindingMethodsActivity : AppCompatActivity() {
    private val user: ObservableUser by lazy {
        ObservableUser("张三", ObservableInt(2))
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityObservableBindingMethodsBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_observable_binding_methods)
        binding.user = user
    }

    fun addLike(view: View) {
        user.like.set(user.like.get() + 1)
    }

}

在这里插入图片描述在这里插入图片描述

提供自定义逻辑

一些属性需要自定义绑定逻辑,Android 框架类的特性已经创建了 BindingAdapter 注释.If we want to take the above exampletint属性和srcProperties are implemented via a custom property:
ObservableBindingAdapterUser

package com.anniljing.jetpackviewmodel.model

import androidx.databinding.ObservableInt

class ObservableBindingAdapterUser {
    var like: ObservableInt = ObservableInt(0)
        set(value) {
            field = value
        }
    var popularity: ObservableInt by ::like
}

BindingMergeAdapters

package com.anniljing.jetpackviewmodel.util

import android.content.Context
import android.content.res.ColorStateList
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.core.widget.ImageViewCompat
import androidx.databinding.BindingAdapter
import androidx.databinding.ObservableInt
import com.anniljing.jetpackviewmodel.R

object BindingMergeAdapters {
    @BindingAdapter("mergeTintAndSrc")
    @JvmStatic fun mergeTintAndSrc(imageView: ImageView, mergeType: ObservableInt){
        val context:Context=imageView.context
        imageView.setImageResource(R.drawable.ic_whatshot_black_96dp)
        if (mergeType.get()>4){
            ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(ContextCompat.getColor(context, R.color.popular)))
        }else if (mergeType.get()>9){
            ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(ContextCompat.getColor(context, R.color.star)))
        }
    }
}

activity_observable_binding_adapter

<?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">

    <data>

        <variable
            name="user"
            type="com.anniljing.jetpackviewmodel.model.ObservableBindingAdapterUser" />
    </data>

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

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{Integer.toString(user.like)}" />

        <ImageView
            app:mergeTintAndSrc="@{user.popularity}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="addLike"
            android:text="Like" />
    </LinearLayout>
</layout>

ObservableBindingAdapterActivity

package com.anniljing.jetpackviewmodel.activity

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.anniljing.jetpackviewmodel.R
import com.anniljing.jetpackviewmodel.databinding.ActivityObservableBindingAdapterBinding
import com.anniljing.jetpackviewmodel.model.ObservableBindingAdapterUser

class ObservableBindingAdapterActivity : AppCompatActivity() {
    private val observableUser: ObservableBindingAdapterUser by lazy {
        ObservableBindingAdapterUser()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityObservableBindingAdapterBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_observable_binding_adapter)
        binding.user = observableUser
    }

    fun addLike(view: View) {
        observableUser.like.set(observableUser.like.get() + 1)
    }

}
原网站

版权声明
本文为[The rest of my life love static]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/223/202208110515270119.html