如何应对 Android 面试官 -> 玩转 JetPack ViewBinding

前言


本章为 DataBinding 先做个铺垫,讲解下 ViewBinding

ViewBinding 主要是用来释放 findViewById 当我们在实际业务开发中如果不需要 DataBinding 的强大功能的时候(DataBinding 很重,layout 内部复杂,耗费性能),可以使用 ViewBinding;

基础使用


模块的 build.gradle 中,声明 closure

arduino 复制代码
// 启用ViewBinding
viewBinding {
   enabled true
}

和 DataBinding 的启用方式一样;

启用之后,我们就不需要 ButterKnife 以及 findViewById 这种方式了;

我们先来声明 xml 文件,取名叫 activity_main.xml

ini 复制代码
<?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">

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/tv3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

代码很简单,就是界面上放了三个 TextView,然后,我们在 Activity 中通过 ViewBinding 将这 xml 和 Activity 关联起来;

当我们通过 studio 创建这个 xml 的时候,gradle 插件就帮我们生成了一个类,根据 activity_main 这个名字生成了一个 ActivityMainBinding 类;然后我们就可以在 Activity 中调用这个类来将 xml 和 Activity 绑定到一起;

scala 复制代码
// ViewBinding背后不是用 APT 注解处理器 使用什么?  答:gradle插件
public class MainActivity extends AppCompatActivity {

    ActivityMainBinding mainBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mainBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(mainBinding.getRoot());

        mainBinding.tv1.setText("AAA");
        mainBinding.tv2.setText("BNB");
        mainBinding.tv3.setText("DDDD");
    }
}

可以看到,ViewBinding 并不需要在 xml 中搞什么复杂的 layout 标签嵌套之类的;也不需要在 Activity 中声明 findViewById 了;

ViewBinding 背后不是用 APT 注解处理器;那么它使用的是什么?答:gradle插件;

通过 gradle 插件提升了编译速度,不像 DataBinding 那么耗费性能;

与 kotlin 绑定机制的差异

接下来讲一下两者的差异

kotlin 的绑定启用

arduino 复制代码
plugins {
    // 有绑定机制后,就不需要 findViewById   gradle插件
    id 'kotlin-android-extensions' // 启用 绑定机制
}

kotlin 的绑定也是在 build.gradle 中启用 kotlin 的一个 gradle 插件;

启用这个插件之后,Activity 中可以直接使用,但是这个必须在 kt 文件中,java 中是不好使的;

kotlin 复制代码
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
// 核心逻辑
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity  : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 绑定机制的缺点
        setContentView(R.layout.activity_main)
        tv1.text = "AAA"
        tv2.text = "BBB"
        tv3.text = "CCC"

    }
}

kotlin 的这个绑定机制有个缺陷,就是可以在当前的 Activity 中绑定任何 xml,但是,我们需要通过 setContentView 绑定 xml 和 Activity,如果在 Activity 中访问了其他 xml 中的元素,就会导致启动崩溃;

kotlin 复制代码
// 绑定机制的缺点1
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.test.*

class MainActivity  : AppCompatActivity() {

    var vb: ActivityMainBinding ? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 绑定机制的缺点2
        setContentView(R.layout.activity_main)
        tv1.text = "AAA"
        tv2.text = "BBB"
        tv3.text = "CCC"
        // 绑定机制的缺点3
        button.text = "" // 人为失误,有隐患,让开发者犯错*/
    }
}

ViewBinding 则不会产生上述的错误;因为我们通过 ViewBinding 只能访问到当前绑定的 xml 中的元素;

Fragment 中的基础使用


java 复制代码
@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        FragmentBlankBinding fragmentBlankBinding = FragmentBlankBinding.inflate(getLayoutInflater());
        return fragmentBlankBinding.getRoot();
    }

和 Activity 的用法基本一致;

简单原理


我们开启 ViewBinding 之后,当声明一个 xml 的时候,会自动的在 moudlue -> build -> generated -> data_binding_base_class_source_out 下生成相关的类;

随便打开一个类看下:

本质上还是需要 findViewById 只是它帮我们生成了而已;

好了,ViewBinding 就讲到这里吧,本章只是对 DataBinding 进行一个铺垫,重点讲解 DataBinding,感兴趣的可以继续探索下 ViewBinding 的原理;

欢迎三连


来都来了,点个关注,点个赞吧,你的支持是我最大的动力~

相关推荐
shenshizhong1 天前
Compose + Mvi 架构的玩android 项目,请尝鲜
android·架构·android jetpack
alexhilton5 天前
学会在Jetpack Compose中加载Lottie动画资源
android·kotlin·android jetpack
ljt27249606618 天前
Compose笔记(六十一)--SelectionContainer
android·笔记·android jetpack
QING6189 天前
Jetpack Compose 中的 ViewModel 作用域管理 —— 新手指南
android·kotlin·android jetpack
惟恋惜9 天前
Jetpack Compose 的状态使用之“界面状态”
android·android jetpack
喜熊的Btm9 天前
探索 Kotlin 的不可变集合库
kotlin·android jetpack
惟恋惜9 天前
Jetpack Compose 界面元素状态(UI Element State)详解
android·ui·android jetpack
惟恋惜9 天前
Jetpack Compose 多页面架构实战:从 Splash 到底部导航,每个 Tab 拥有独立 ViewModel
android·ui·架构·android jetpack
alexhilton11 天前
Jetpack Compose 2025年12月版本新增功能
android·kotlin·android jetpack