Jetpack之binding,ViewBinding和DataBinding

772 阅读3分钟
  • ViewBinding:简单来说,代替findViewById,更大的优点是空安全。
  • DataBinding:MVVM好伙伴

一、ViewBinding

官方文档:developer.android.google.cn/topic/libra…


ViewBinding是区分Android studio版本的。可以分为4.0之前和之后

// 3.6,4.0之前
android {
    ...
    viewBinding {
        enabled = true
    }
}

// Android Studio 4.0之后
android {
    ...
    buildFeatures {
        viewBinding = true
    }
}

View Binding是Android Studio 3.6推出的新特性,目的是为了替代findViewById(内部实现还是使用findViewById)

优点

  • Null 安全:由于视图绑定会创建对视图的直接引用,因此不存在因视图 ID 无效而引发 Null 指针异常的风险。此外,如果视图仅出现在布局的某些配置中,则绑定类中包含其引用的字段会使用 @Nullable 标记。

  • 类型安全:每个绑定类中的字段均具有与它们在 XML 文件中引用的视图相匹配的类型。这意味着不存在发生类转换异常的风险。

简单使用

android {
    ...
    buildFeatures {
        viewBinding = true
    }
}
class MainActivity : AppCompatActivity() {
    private lateinit var mainBinding:ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 调用生成的绑定类中包含的静态 inflate() 方法
        mainBinding = ActivityMainBinding.inflate(layoutInflater)
        mainBinding.tvName.text= "张三丰长大了"

        // 当然了,依然可以 findViewById,只是一般没必要了
//        mainBinding.root.findViewById<>()

        mainBinding.tvAge.text = "20"
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        >
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="小张三丰"
             />

        <TextView
            android:id="@+id/tv_age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="18岁"
            android:layout_marginTop="10dp"
            />

        <TextView
            android:id="@+id/tv_diary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="日记本"
            android:layout_marginTop="10dp"
            />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

个别页面不想用 viewBinding

如果想在生成绑定类时忽略某个布局文件,将 tools:viewBindingIgnore="true" 属性添加到相应布局文件的根视图中,即可。

DataBinding

开启DataBinding是区分Android studio版本的。可以分为4.0之前和之后

// 4.0之前
android {
    ...
    dataBinding {
        enabled = true
    }
}

// Android Studio 4.0之后
android {
    ...
    buildFeatures {
        dataBinding = true
    }
}

二、DataBinding

说到DataBingding,就避免不开MVVM。(M 是指 Model,V 是指 View,VM 是指ViewModel)

优点

  • 替换 findViewById ,减少模板代码
  • 解决类型安全问题
  • 解决空安全问题
  • 保证了数据的一致性

如何使用

  • 1、 开启 dataBinding = true
  • 2、xml根布局必须是以 layout 开始
  • 3、根布局 layout下需要有个 data 标签data 标签用于声明要用到的变量以及变量类型,要实现 MVVM 的 ViewModel 就需要把数据(Model)与 UI(View)进行绑定,data 标签的作用就像一个桥梁搭建了 View 和 Model 之间的通道)
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="viewmodel"
            type="com.myapp.data.ViewModel" />
    </data>
    <ConstraintLayout... /> <!-- UI layout's root element -->
</layout>

小技巧:生成layout

在布局文件,按下option+回车(alt+回车),即可快速在最外层的layout。(注意一定是开启了 dataBinding = true 的前提下 ) image.png

并且还会生成data标签。

从最简单的的使用说起

buildFeatures {
    dataBinding = true
}

.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val mainBinding =
            DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        var info = UserInfo()
        info.name = "南极企鹅"
        info.hobby = "打阿豆"
        
        mainBinding.userInfoBean = info
    }
}

.

<?xml version="1.0" encoding="utf-8"?>
<!--根布局必须是layout-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
<!--    绑定数据-->
    <data>
        <variable
            name="userInfoBean"
            type="com.am.databindingtest.UserInfo" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center"
        >
        <TextView
            android:id="@+id/tv_name"
            android:text="@{userInfoBean.name}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="用户名"
           />

        <TextView
            android:id="@+id/tv_hobby"
            android:text="@{userInfoBean.hobby}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="爱好"
            android:layout_marginTop="10dp"
            />
    </LinearLayout>
</layout>

运行:

image.png .

关于xml里的data标签,还有其他的使用方法

data 之 import 方式

<?xml version="1.0" encoding="utf-8"?>
<!--根布局必须是layout-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
<!--    绑定数据-->
    <data>
<!--        import 进来,这样就不用每次都指明整个包名路径了-->
        <import type="com.am.databindingtest.UserInfo"/>
        <variable
            name="userInfoBean"
            type="UserInfo" />
    </data>

我们写的类需要全路径引入,但是如果是String之类,就可以直接使用,因为java.lang.* 包中的类会被自动导入,所以可以直接使用

data 之 alias 别名

如果存在 import 的类名相同的情况,可以使用 alias 指定别名

    <data>
        <import type="com.am.databindingtest.UserInfo" />
        <import
            alias="TempUser"
            type="com.am.databindingtest.xxxxx.UserInfo" />
        <variable
            name="userInfo"
            type="User" />
        <variable
            name="tempUserInfo"
            type="TempUser" />
    </data>

其他

通过Model改变视图,这是单向绑定,如果通过视图可以改变Model的值,那么就是双向绑定。

{}里面可以包含很多的表达式

databinding可以绑定事件

其他的懒得写了,看下其他文章吧 cloud.tencent.com/developer/a…