4

Google挖坑后人埋-ViewBinding(上)

 2 years ago
source link: https://blog.csdn.net/eclipsexys/article/details/116141828
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Google挖坑后人埋-ViewBinding(上)

https://developer.android.com/topic/libraries/view-binding

Warning: The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.

kotlin-android-extensions是个好东西,可以帮我们省掉很多需要写findViewById的场景。相信大部分的Kotlin开发者都在使用它进行Android开发,而且在之前的Android Studio创建Android项目时,都会自动帮你依赖:

apply plugin: 'kotlin-android-extensions'

但是现在你再创建Android项目,就不会自动帮你依赖了,其原因就是kotlin-android-extensions这个插件已经被废弃了。

为啥?Google这新技术迭代跟玩一样啊,有kotlin-android-extensions插件我不用,我就手写,哎,就是玩儿~

其实,kotlin-android-extensions插件还是有很多问题的,虽然它很方便,但实际上,这是牺牲掉一部分内存来换取的方便,在对应用性能日益严格的今天,这种做法势必会被淘汰掉。

kotlin-android-extensions三宗罪

通过反编译kotlin-android-extensions的代码,你就会发现,通过kotlin-android-extensions,它会在代码中创建一个HashMap,用来存放所有的id和对应的View的缓存,如果缓存中没有需要的View,那么就通过findViewById去创建,否则就直接获取,这就是它的原理。

资源ID重名

由于kotlin-android-extensions是通过view的id名直接引用的,所以多个布局间的同名id,就需要手动对import进行重命名处理,而且经常会引用错误的布局文件,导致运行崩溃。

Kotlin only

只有Kotlin才可以使用。

当然,ViewBinding也不是银弹,对比kotlin-android-extensions,它也有一些问题:

  • 使用比kotlin-android-extensions复杂

  • 依然有需要手动处理的场景

当然也有一些优势:

  • Kotlin Java通吃

ViewBinding初步

ViewBinding就是为了解决kotlin-android-extensions的这些使用问题而诞生的,它的目的只有一个,那就是避免重复的findViewById的同时,不影响应用性能。

要使用ViewBinding非常简单:

当我们开启ViewBinding之后,在编译时,AGP会自动帮我们给每个xml布局创建一个Binding类,Binding类的命名规则是将xml文件按驼峰方式重命名后,再加上Binding作为结尾得到的,例如splash_layout.xml会自动生成一个SplashLayoutBinding的类文件。

跨Module使用的时候,子Module也需要开启ViewBinding功能

这个Binding文件,实际上就相当于kotlin-android-extensions的HashMap,同时由于它在编译时就生成了,就不会占用运行时内存。

虽然这里生成了大量的XXXBinding文件,但是对编译速度的影响和生成Apk大小的影响几乎可以忽略:

  • 未使用的XXXBinding文件会在混淆时被删除

  • 编译器生成Binding文件的速度极快,同时是增加更新

ignore

如果你不想生成这个Binding类,可以通过下面的方式来过滤掉该文件的生成。

开启ViewBinding后,会给xml布局生成XXXBinding文件,位于build/generated/data_binding_base_class_source_out/目录下。

Activity

在Activity中使用ViewBinding一般需要使用到Binding类的inflate方法,一般使用方式如下所示。

Binding类还有一个getRoot方法,用来返回xml布局的根元素,所以setContentView(R.layout.xxxx)就可以替换为:

setContentView(binding.root)

Fragment

在Fragment中使用ViewBinding会比在Activity中使用要复杂一点,因为需要保证Binding类与Fragment的生命周期同步,示例代码如下所示。

_binding和binding傻傻分不清吗?其实没什么区别,这是为了在Kotlin中将不可空类型置空的一种妥协方式,同样的代码逻辑,在Java中,就会非常简单了。

Adapter

除了Activity和Fragment,在Adapter中使用,特别是RecyclerView中使用,也是一个非常常见的使用场景。利用kotlin-android-extensions,我们可以借助LayoutContainer来在ViewHolder中直接使用View id,那么在ViewBinding中,使用方式就更简单了。

其实核心代码依然是inflate,套路都是一样的。

Dialog

原理依然是一个套路。

Include、Merge

在布局中通过include来引入新的布局也是一个很常用的方式,kotlin-android-extensions由于底层使用的是运行时findViewById,所以不会存在什么问题,但是ViewBinding就不一样了,由于它是编译时生成,所以需要指定id才可以使用。

因此,在ViewBinding中使用include的layout,有两种方式,一种是给include设置id,这样通过id就可以直接引用,代码如下所示。

这样使用的时候,代码如下:

XXXBinding.xxxInclude.xxxx

另外一种方式是直接使用新的Binding文件,因为所有的xml布局文件都会生成Binding,所以可以直接使用这个Binding文件。

IncludeXXXXXBinding.bind(binding.root).xxxxx

这种方式还可以解决Merge的引入问题。

更新一时爽,迁移火葬场。

目前还未找到现有项目从kotlin-android-extensions迁移到ViewBinding的好办法,如果当前的项目大量使用kotlin-android-extensions,那么迁移起来,就是一个巨大的工程,没有migration tools,也不能通过脚本更换,确实没找到什么好的办法。

向大家推荐下我的网站 https://xuyisheng.top/  点击原文一键直达

专注 Android-Kotlin-Flutter 欢迎大家访问


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK