【Jetpack】学穿:ViewBinding → 视图绑定(下)

简介: 手机厂商还没卷完Android 12,Android 13 就悄然声息地来了,距离Google 2008年9月22日发布Android 1.0,已过去13个年头。

② Kotlin委托 + lifecycle组件


有些朋友可能觉得写在父类中侵入性太强,接着试下用其他方式进行封装,先看原始Activity:


网络异常,图片无法展示
|


要把圈住的代码干掉,先是 泛型传递问题,泛型在进JVM前会被擦除,可在运行时通过反射获得,还可以通过实例化类类型代替类引用,如:


fun <T: Activity> FragmentActivity.startActivity(context: Context, clazz: Class<T>) {
    startActivity(Intent(context, clazz))
}
// 调用处
startActivity(context, MainActivity::class.java)


而在Kotlin中还可以用 inline 定义一个 内联函数 (编译时自动替换到调用位置),配合 reified 具体化(类型不擦除),得到泛型类型的Class,如:


inline fun <reified T : Activity> Activity.startActivity(context: Context) {
    startActivity(Intent(context, T::class.java))
}
// 调用
startActivity<MainActivity>(context)


可以,配合反射invoke()调用,随手写上一个扩展方法:


网络异常,图片无法展示
|


调用下:


网络异常,图片无法展示
|


看似十拿九稳,结果一跑就崩:


网络异常,图片无法展示
|


不过也在意料之内,Activity还没onCreate()就初始化了,不空才怪,可以利用 标准委

托-lazy 延迟初始化,修改后的代码:


网络异常,图片无法展示
|


调用下:


网络异常,图片无法展示
|


运行通过,你还可以把还可以把setContentView()也塞到扩展中:


网络异常,图片无法展示
|


配合lifecycle组件,顺手把Fragment的也写出来:


网络异常,图片无法展示
|


调用下:


网络异常,图片无法展示
|


对了,如果还不想使用反射,可以利用Kotlin高阶函数,示例如下:


网络异常,图片无法展示
|


调用下:


网络异常,图片无法展示
|


啧啧啧,你还可以不用lazy,自己重写ReadOnlyProperty,这里只是试试水封装,并没用到生产上,更完善的封装方案可自行参考下述开源库:



0x5、原理


AGP会为模块中每个XML生成一个绑定类,该类的实例会直接引用布局中声明了资源id的View


① 自动生成的绑定类


打开:module模块名/build/generated/intermediates/javac/渠道/包名/databinding


可以看到 (基于AGP 7.1.1,不同AGP版本可能不一样):


网络异常,图片无法展示
|


自动生成的class文件,随手打开一个:


网络异常,图片无法展示
|


所以本质上还是findViewById,只是自动生成了控件实例,并一一对应,接着简单了解下大概的生成流程。


② 生成Java类


执行gradlew assembleDebug,在Task构建列表没找到ViewBinding,却找到了DataBinding:


网络异常,图片无法展示
|


打开AGP源码,全局搜 dataBindingMergeGenClassesDataBindingMergeBaseClassLogTask.kt


网络异常,图片无法展示
|


跟到:TaskManager.ktcreateDataBindingTasksIfNecessary


网络异常,图片无法展示
|


2333,跟DataBinding混一起了,所以 ViewBinding其实只是DataBinding功能的一小部分~


看回:DataBindingMergeBaseClassLogTask,增量和全量执行动作:


网络异常,图片无法展示
|


跟下:DataBindingMergeBaseClassLogDelegate


网络异常,图片无法展示
|


跟下:DataBindingMergeBaseClassLogRunnable


网络异常,图片无法展示
|


判断文件是否新建、修改、或移除,跟下是哪个文件:


网络异常,图片无法展示
|


网络异常,图片无法展示
|


全局搜下这个结尾的文件,在下述目录找到了它:


网络异常,图片无法展示
|


网络异常,图片无法展示
|


不难看出是:XML名称和ViewBinding类的映射,往下看 DataBindingMergeDependencyArtifactsTask,BR相关的,目前不知道是干嘛的。

再往下走:DataBindingGenBaseClassesTask → CreationAction


网络异常,图片无法展示
|


跟下:DataBindingGenBaseClassesTask → @TaskAction


网络异常,图片无法展示
|


先看 buildInputArgs(),构建输入参数,同样对增量和全量编译进行了不同的处理,然后返回配置实例


网络异常,图片无法展示
|


接着看 CodeGenerator 类,见名知意,代码生成器


网络异常,图片无法展示
|


这里直接索引不到 BaseDataBinder,需要另外依赖:databinding-compiler-common


implementation 'androidx.databinding:databinding-compiler-common:7.1.0'


async后就可以了,打开 MVNResponsitory - Gradle » 7.1.0 可以看到它依赖了47个运行时库~


网络异常,图片无法展示
|


跟下:BaseDataBinder → generateAll()


网络异常,图片无法展示
|


跟下:ViewBinderGenerateJava.kt → toJavaFile() → JavaFileGenerator


网络异常,图片无法展示
|


Java文件就是从这里构造出来的,具体构造过程,感兴趣的可以自己翻阅下此文件。

另外,如果你想了解布局采集和写Layout部分的逻辑,可以参考 《ViewBinding 的本质》,笔者卷不动了...


0x6、一些补充


① 与DataBinding的区别


可以把ViewBinding看做DataBinding功能的子集,它有的功能DataBinding都有,不需要数据绑定单纯想替代findViewById 可以用ViewBinding。


② 不用build就能自动生成Java类


笔者猜测:AS起了一个进程 Filesystem events processor 用于监听文件变化,有文件变动时回调执行ViewBinding相关的Task。


③ KAE库过时,迁移Parcelable


Module 层次的 build.gradle 添加 kotlin-parcelize 插件。


以上就是本节的全部内容,有疑问或补充欢迎评论区指出,谢谢~


参考文献:



相关文章
|
Java Android开发 Windows
用Jetpack Compose Desktop做一个推箱子小游戏,演示键盘事件绑定的方式
做Windows桌面游戏是少不了与键盘交互的,不过其实并非我们做Windows桌面应用才需要小游戏,如果要做安卓机顶盒APP,也是要监听键盘的,只不过那是遥控器的键盘,方式其实也是一样的。
297 0
用Jetpack Compose Desktop做一个推箱子小游戏,演示键盘事件绑定的方式
|
Android开发 Windows 容器
浅析 JetPack Compose 是如何安装到View视图上
为什么 Compose 无需在意 view 层级问题,怎样嵌套都行? (最简单10s就能明白);
275 0
浅析 JetPack Compose 是如何安装到View视图上
|
XML Java API
Jetpack 系列(6)—— ViewBinding 与 Kotlin 委托双剑合璧
Jetpack 系列(6)—— ViewBinding 与 Kotlin 委托双剑合璧
233 0
Jetpack 系列(6)—— ViewBinding 与 Kotlin 委托双剑合璧
|
API Android开发 Kotlin
【Jetpack】学穿:Activity Results API(下)
【Jetpack】学穿:Activity Results API
371 0
|
API 开发者
【Jetpack】学穿:Activity Results API(中)
【Jetpack】学穿:Activity Results API
244 0
|
API 开发者
【Jetpack】学穿:Activity Results API(上)
【Jetpack】学穿:Activity Results API
221 0
|
存储 缓存 数据管理
【Jetpack】学穿:ViewModel → 视图模型(下)
本节带来组件 → ViewModel 视图模型的解读!叫 视图数据 可能更贴切,有人也叫 视图状态
274 0
|
XML 数据格式 Python
【Jetpack】学穿:ViewModel → 视图模型(中)
本节带来组件 → ViewModel 视图模型的解读!叫 视图数据 可能更贴切,有人也叫 视图状态
164 0
|
存储 编解码 数据管理
【Jetpack】学穿:ViewModel → 视图模型(上)
本节带来组件 → ViewModel 视图模型的解读!叫 视图数据 可能更贴切,有人也叫 视图状态
208 0
|
缓存 Java 编译器
【Jetpack】学穿:LiveData → ???(下)
在开始这篇文章前,我就遇到了第一个关于LiveData的问题:该怎么翻译这个词呢?
317 0