Android 架构组件 DataBinding(一)

目录

  • 简介
  • 开始使用:
  • 如何使用(介绍)
  • 布局和绑定表达式
    • 布局
      • 标签的内容
      • 标签中的内容
        • 标签中内容详解
      • view 根元素
    • 生成绑定类绑定布局
      • 使用DataBindingUtil 的方式
      • 使用 xmlBinding 的方式
    • 开发中使用哪种?
    • 绑定表达式
      • 在布局中设置动态属性
      • 表达式语言
        • 常见的表达式语法
        • 缺少的运算
        • Null 合并运算符
        • 属性引用
        • 避免出现NULL指针异常
        • 集合
        • 字符串字面量
        • 资源
      • 事件处理
        • 处理事件的方式
          • 方法引用
          • 监听器绑定
          • 方法引用和监听器绑定之间的区别
        • 导入、变量和包含
            • 导入
            • 变量
            • 包含

简介

DataBinding 是一种支持库,借助该库,您可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。库是一种支持库,借助该库,您可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。

借助布局文件中的绑定组件,您可以移除 Activity 中的许多界面框架调用,使其维护起来更简单、方便。还可以提高应用性能,并且有助于防止内存泄漏以及避免发生 Null 指针异常。

开始使用:

DataBinding 不但灵活而且兼容性广。因此大家可以在Android 4.0(API 级别 14 )的时候进行使用。
如果想要使用 DataBinding,那么大家就需要在Module 的build.gradle 中添加

android {
        dataBinding {
            enabled = true
        }
    }
    

或者

android {
        dataBinding.enabled = true
    }
    

如何使用(介绍)

如果需要使用DataBinding ,那么大家就需要在xml 布局中符合如下的规则:

  • 使用 包裹整体的内容
  • 使用包裹自己所需要的数据
    如:


    
    

    
    

在代码中生成绑定类绑定布局的方式有两种:

  • 使用 DataBindingUtil 的方式
  • 使用 XMLBinding 方式

布局和绑定表达式

布局

与普通的xml不同,DataBinding布局文件以根标记 layout 开头,后跟 data 元素和 view 根元素。

标签的内容

标签中盛放xml文件中的命名空间。如:

  • 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

标签中的内容

标签中盛放数据类型。如:
string 数据类型可以使用如下方式导入

标签中内容详解

中的type 属于 要导入的名称, alias 属于自己定义的别名,可以在布局中进行使用和类目相同的类进行区分。
中的 name 表示在要在布局中使用的名称,和上面的别名相同。
当然 仅仅是导入使用的类型,如果想要色湖之数据还是需要在 进行设置。

view 根元素

这里使用的View 根标签和我们使用的正常布局一样。

生成绑定类绑定布局

首先我们要知道,系统会为所有使用的布局生成一个绑定类,格式为布局文件的名称转换为 Pascal 大小写形式并在末尾添加 Binding 后缀。如activity_main.xml 生成的类就是ActivityMainBinding。
生成的绑定类将布局与布局中的视图关联起来。这些类都是从ViewDataBinding 继承而来的。

在上面我们介绍了代码中绑定布局的方式有两种,现在我们就介绍一下。

使用DataBindingUtil 的方式

如图我们可以看见DataBindingUtil 中可以使用 inflate 、bind 、setContentVIew 的方式绑定布局。
其中:
inflate :可以在任意地方进行使用,一般在Fragment / recyclerview 等地方进行使用
bind : 可以在任意地方进行使用。
setContentVIew : 只可以在Activity 中进行使用。
Android 架构组件 DataBinding(一)_第1张图片

使用 xmlBinding 的方式

xmlBinding 和上面的DataBindingUtil 相似。
Android 架构组件 DataBinding(一)_第2张图片
只不过如果使用 xmlBinding 之后必须要使用 setContentView (Activity 中)重新设置数据。

开发中使用哪种?

我个人推荐使用 DataBIndingUtil 的方式。大家都知道如果要写项目,那么就会抽取出Base 类,所以我们为了使用的方便一般就自己对于setCOntentView方法进行各种设置。比如我的BaseActviity。

abstract class BaseActviity : AppCompatActivity() {
    var mBInding: T? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBInding =  DataBindingUtil.setContentView(this,getLayoutIds())
    }
    abstract  fun  getLayoutIds(): Int
}

这样我们就可以在自己的类中使用统一的方式进行设置。

绑定表达式

在布局中设置动态属性

如果有一个 User 类,类中有name 和 age 两个属性,那么我们在布局中设置一个textview 的name 为user的name我们可以在布局中直接使用。



    
        
        
    
    
        
    

当然,我们这里只是将数据类型添加到了布局中,但是布局仍然不知道内部的数据是上面,所以我们需要对于数据和布局进行绑定。
如,下面的例子:

        val mBinding = setContentView(this, R.layout.activity_main)
        mBinding.user = User("蔡依林",22)

表达式语言

常见的表达式语法

表达式语言与托管代码中的表达式非常相似。您可以在表达式语言中使用以下运算符和关键字:

  • 算术运算符 + - / * %
  • 逻辑运算符 && ||
  • 移位运算符 >> >>> <<
  • 一元运算符 + - ! ~
  • 二元运算符 & | ^
  • 三元运算符 ?:
  • instanceof
  • 分组运算符 ()
  • 字符串连接运算符 +
  • 字面量运算符 - 字符、字符串、数字、null
  • 类型转换
  • 方法调用
  • 字段访问
  • 数组访问 []

缺少的运算

  • this
  • super
  • new
  • 显式泛型调用

Null 合并运算符

如果左边运算数不是 null,则 Null 合并运算符 (??) 选择左边运算数,如果左边运算数为 ,则选择右边运算数

android:text="@{user.displayName ?? user.lastName}"

这在功能上 等效于 三元运算符

android:text="@{user.displayName != null ? user.displayName : user.lastName}"

属性引用

这个功能就是在上面的时候进行使用的@{}的方式,这里不再次进行介绍。

避免出现NULL指针异常

生成的数据绑定类会自动检查是否有null 值,并且避免空指针异常。例如,在表达式 @{user.name} 中,如果 user 为 Null,则为 user.name 分配默认值 null。如果您引用 user.age,其中 age 的类型为 int,则数据绑定使用默认值 0。

集合

为方便起见,可使用 [] 运算符访问常见集合,例如数组、列表、稀疏列表和映射。

注意:要使 XML 不含语法错误,您必须转义 < 字符。例如:不要写成 List 形式,而是必须写成 List <;String>。

您还可以使用 object.key 表示法在映射中引用值。例如, @{map[key]} 可替换为 @{map.key}。

字符串字面量

您可以使用单引号括住特性值,这样就可以在表达式中使用双引号,如以下示例所示

android:text='@{map["firstName"]}'

也可以使用双引号括住特性值。如果这样做,则还应使用反单引号 ` 将字符串字面量括起来:

android:text="@{map[`firstName`]}"

资源

您可以使用以下语法访问表达式中的资源:

android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"

格式字符串和复数形式可通过提供参数进行求值:

android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"

当一个复数带有多个参数时,应传递所有参数:


      Have an orange
      Have %d oranges
      
    android:text="@{@plurals/orange(orangeCount, orangeCount)}"
    

某些资源需要显式类型求值,如下表所示:

类型 常规引用 表达式引用
String[] @array @stringArray
int[] @array @intArray
TypedArray @array @typedArray
Animator @animator @animator
StateListAnimator @animator @stateListAnimator
color int @color @color
ColorStateList @color @colorStateList

事件处理

通过数据绑定,您可以编写从视图分派的表达式处理事件(例如,onClick() 方法)。事件特性名称由监听器方法的名称确定,但有一些例外情况。例如,View.OnClickListener 有一个 onClick() 方法,所以该事件的特性为 android:onClick。

有一些专门针对点击事件的事件处理脚本,这些处理脚本需要使用除 android:onClick 以外的特性来避免冲突。您可以使用以下特性来避免这些类型的冲突

Listener setter 特性
SearchView setOnSearchClickListener(View.OnClickListener) android:onSearchClick
ZoomControls setOnZoomInClickListener(View.OnClickListener) android:onZoomIn
ZoomControls setOnZoomOutClickListener(View.OnClickListener) android:onZoomOut

当然这些事件我们也可以自己进行定义,我们之后再说。

处理事件的方式

**方法引用:**在表达式中,您可以引用符合监听器方法签名的方法。当表达式求值结果为方法引用时,数据绑定会将方法引用和所有者对象封装到监听器中,并在目标视图上设置该监听器。如果表达式的求值结果为 null,则数据绑定不会创建监听器,而是设置 null 监听器。
**监听器绑定:**这些是在事件发生时进行求值的 lambda 表达式。数据绑定始终会创建一个要在视图上设置的监听器。事件被分派后,监听器会对 lambda 表达式进行求值。

方法引用

事件可以直接绑定到处理程序方法,类似于android:onClick可以分配给活动中的方法…
使用方式:
1… 定有一个类,类中有一个需要传递view 的方法

open class Click {
    fun ztoastClcik(view : View){
    }
}
  1. 在xml 中进行设置:在这里通过 @{类名(自己设置的variable 中的name):: 方法名称}


    
        
        
    
    
        
  1. 在代码中进行设置
    mBinding.click =  Click()

方法引用大家可以认为是一个官方原生的监听器,里面只可以传递view,不可以传递其他参数。我个人认为局限性太大。

监听器绑定

监听器绑定是在事件发生时运行的绑定表达式。它们类似于方法引用,但允许您运行任意数据绑定表达式。此功能适用于 Gradle 2.0 版及更高版本的 Android Gradle 插件。
使用方式:

  1. 定义一个类,类中定义一个方法
open class Click {
    fun toastClcik(context:Context, msg: String) {
        Toast.makeText(context,msg,Toast.LENGTH_SHORT).show()
    }
}
  1. 在xml 文件中进行使用
    这里我们使用的方式是 @{(view)->类名.方法名(所传递的参数)}. 我们可一点击进入(view)中发现他调用的其实是
 public interface OnClickListener {
        void onClick(View var1);
    }

当然了,在这里也可以不传递。所传递的参数通过 进行设置。



    
        
        
        
        
    
    
        

3.在代码中进行设置

        mBinding.msg = "按钮被点击了"
        mBinding.contexts = this
        mBinding.click =  Click()

需要注意的是,如果您监听的事件返回类型不是 void 的值,则您的表达式也必须返回相同类型的值。

监听器表达式功能非常强大,可以使您的代码非常易于阅读。另一方面,包含复杂表达式的监听器会使您的布局难以阅读和维护。这些表达式应该像将可用数据从界面传递到回调方法一样简单。您应该在从监听器表达式调用的回调方法中实现任何业务逻辑。

方法引用和监听器绑定之间的区别

监听器实现是在绑定数据时创建的,而不是在事件触发时创建的。

导入、变量和包含

导入

通过导入功能,您可以轻松地在布局文件中引用类,就像在托管代码中一样。您可以在 data 元素使用多个 import 元素,也可以不使用。
当类名有冲突时,其中一个类可使用别名重命名。以下示例将 com.example.real.estate 软件包中的 View 类重命名为 Vista:

变量

您可以在 data 元素中使用多个 variable 元素。每个 variable 元素都描述了一个可以在布局上设置、并将在布局文件中的绑定表达式中使用的属性。
变量类型在编译时进行检查,因此,如果变量实现 Observable 或者是可观察集合,则应反映在类型中。如果该变量是不实现 Observable 接口的基类或接口,则变量是“不可观察的”。

如果不同配置(例如横向或纵向)有不同的布局文件,则变量会合并在一起。这些布局文件之间不得存在有冲突的变量定义。

在生成的绑定类中,每个描述的变量都有一个对应的 setter 和 getter。在调用 setter 之前,这些变量一直采用默认的托管代码值,例如引用类型采用 null,int 采用 0,boolean 采用 false,等等。

系统会根据需要生成名为 context 的特殊变量,用于绑定表达式。context 的值是根视图的 getContext() 方法中的 Context 对象。context 变量会被具有该名称的显式变量声明替换。

包含

通过使用应用命名空间和特性中的变量名称,变量可以从包含的布局传递到被包含布局的绑定。


    
       
           
       
       
           
           
       
     

数据绑定不支持 include 作为 merge 元素的直接子元素。

你可能感兴趣的:(Android,kotlin)