[译]Finding Views by ID的演进

本文探讨了Android中从findViewById()到ViewBinding的视图引用获取方法的演变,包括Butterknife、KotlinSynthetics、DataBinding等技术,分析了它们的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者:Wajahat Karim

时间:2020/4/1

原文: Evolution of Finding Views by ID in Android

findViewById() vs Butterknife vs Kotlin Synthetics vs DataBinding vs ViewBindings

长久以来,Android开发人员一直在努力解决一个简单但烦人的问题。将XML布局中View的引用以完全独立的语言(Java或Kotlin)从其布局视图类(例如Activity或Fragments)中获取。

作为Android的初学者时,我曾感到很困惑。Android SDK提供了一个方法:findViewById()。功能方面,这个方法执行一个单一的任务——在XML布局中查找ID,返回一个View的引用。如果什么都没找到,它将返回NULL,据说它的创造者称其为十亿美元的错误。

在这篇文章中,我将探讨findViewById()如何演进和在“现代Android开发”中如何从XML布局中获取一个View的引用。

——————————————————————————————————

findViewById()方法

显然,首先是findViewById()方法。在API 1中引入,该方法需要一个ID作为参数,返回一个View对象。
在这里插入图片描述

这种方法存在一些问题。

  • 如果在布局中存在该ID的View,则不会出现任何编译错误。相对地,当Android无法在Activity,Fragment,ViewGroup中找到该View时,将在运行时抛出NullPointerException。
  • 如果该View在XML布局中是TextView,并且将其类型转换为Button,在编译期同样不会出错。但运行时会抛出ClassCastException,因为TextView无法转换为Button。

此方法被广泛使用,并且贯穿了Android SDK的整个发展过程。在compileSdk API为26时,略微修改了改方法以消除强制转换问题。
在这里插入图片描述

现在,开发人员无需在代码中手动强转View。如果您引用使用Button来引用TextView的ID,则Android SDK会尝试查找指定ID的Button,并且它将返回NULL,因为无法找到它。

但是在Kotlin中,您仍然需要提供一个View类型像这样:findViewById(R.id.txtUsername) 。这将抛出NullPointerException 如果你没有做空安全检查,但是这个方法不会像之前一样抛出ClassCastException。

分析

  • 类型安全(Type-safe): 在API 26以前,非类型安全
  • 空安全(Null-safe): 无。在使用之前必须进行空检查
  • 样板代码(Boilerplate Code): 很多。你必须为每个在XML布局中使用到的View定义一个单独的变量
  • 构建时间(Build Time): 无差异
  • 语言(Languages): 支持Java和Kotlin

——————————————————————————————————

ButterKnife

很多库都试图通过不同的方法简化findViewById()的使用。特别地,Jake Wharton开源的Butterknife尤为出名并且引起了全球开发者的兴趣。它已经成了避开使用findViewById()的标准方式。

该库使用注解处理,并通过编译期生成的代码使用findViewById()方法从XML布局中获取View。它非常易于使用,并能有效减少开发人员的样板代码。
在这里插入图片描述

Butterknife具有与findViewById几乎相似的问题。然而,它在运行时添加空安全检查来避免NullPointerException。

注意: 现在不推荐使用此工具。请切换到view binding。当然,现有版本将继续维护,但是仅考虑与AGP集成相关的关键错误的修复。功能开发和常规错误的修复已停止。 ——原文:Butterknife Github repository

分析

  • 类型安全(Type-safe): 非类型安全,因为使用了findViewById
  • 空安全(Null-safe): 该库运行时在view访问前做了空判断
  • 样板代码(Boilerplate Code): 通过注解处理器生成代码来减少样板代码
  • 构建时间(Build Time): 构建时间受注解处理影响
  • 语言(Languages): 支持Java和Kotlin

——————————————————————————————————

Kotlin Synthetics

Android SDK现在是Kotlin优先(Kotlin-first)。这意味着Android SDK将首先从Kotlin的角度实现API,然后再为Java添加这些API。

Kotlin引入的最大功能之一是Kotlin扩展方法(Kotlin Extension Methods)。在它的帮助下,Kotlin Synthetics诞生了。Kotlin Synthetics通过自动生成的Kotlin扩展方法,使开发人员可以从XML布局直接访问其视图。
在这里插入图片描述

Kotlin Synthetics调用一次findViewById方法,然后默认情况下将view实例缓存在HashMap中。可以通过Gradle设置将此缓存配置更改为SparseArray或不缓存。

总体而言,Kotlin Synthetics是一种很好的选择,因为它是类型安全的,并且需要通过Kotlin的“?”操作符进行空检查如果view仅在一些布局配置中存在。它不需要开发人员编写额外的代码。但这仅适用于Kotlin项目。

但是,许多开发人员在使用Kotlin Synthetics时遇到了一个小问题。例如,如果您将布局设置为content view,但输入仅在其他布局中存在的ID,IDE将为您自动补全并添加新的import语句。除非开发人员专门检查以确保其import语句仅导入正确的视图,否则没有安全的方法来验证这不会引起运行时问题。

分析

  • 空安全(Null-safe): 通常情况下,它是空安全的。但是,如果视图ID在其他布局中也存在/缺失,那么需要开发人员显示的使用操作符"?"或者在使用前判空。开发人员可能使用了其他布局中的view导致NullPointerException
  • 样板代码(Boilerplate Code): 没有样板代码因为扩展方法生成了。只需要在build.gradle中使用android-kotlin-extension插件。
  • 语言(Languages): 仅支持Kotlin

——————————————————————————————————

Data Binding

Data Binding库是一个Support库,使您可以使用声明式样式(而不是通过编程方式)将布局中的UI元素绑定到应用程序中的数据源。

Data Binding在功能上比其他方法优越得多,因为它不仅为您提供类型安全和null安全的视图引用,而且还允许您直接在XML布局内使用视图映射数据。

您必须手动转换布局来支持Data Binding通过嵌套在标签中。
在这里插入图片描述
使用Data Binding最大的优点是,它使开发人员甚至无需访问Java / Kotlin文件中的视图即可将数据与XML中的视图进行映射。您也可以使用双向绑定来更新XML或数据值,而无需任何listener或callback。

分析

  • 样板代码(Boilerplate Code): 要求每个布局文件都嵌套在标签内。而且,您还必须创建自动生成的绑定类的实例,并将其填充到您的Activity或Fragment中。
  • 构建时间(Build Time): 由于生成布局对应的类文件而增加了构建时间。通常,它很慢,因为您必须手动点击“Make”按钮来为布局更新/生成新的类。
  • 语言(Languages): 支持Java和Kotlin

——————————————————————————————————

View Binding

最近,ViewBinding作为Data Binding库的排序子集在Android Studio 3.6中引入。由于不需要注解处理,因此可以缩短构建时间。它不需要因为嵌套标签而导致过多关注布局文件,默认情况下,它适用所有布局文件。

它与Data Binding唯一的区别在于,该绑定仅用于视图引用。它不执行任何数据映射或双向数据绑定。

如果您只是在寻找一种从布局文件获取视图的好方法,则可以使用ViewBinding代替其他选项。

这仅适用于Android Studio 3.6或更高版本。您可以通过将其添加到app的build.gradle文件中来启用它。
在这里插入图片描述

然后,Android Studio将为您的所有布局文件生成View Binding类。您可以使用这些类在“Activity”或“Fragment”中进行填充,就像在Data Binding中所做的那样。
在这里插入图片描述

如果要跳过某些布局文件,可以通过在布局文件中添加 *tools:viewBindingIgnore =“ true”*来实现。

分析

  • 样板代码(Boilerplate Code): 没有样板代码,因为View Binding类是自动生成的。它只需要在build.gradle中启用View Binding。
  • 构建时间(Build Time): 对构建速度没有影响。 View Binding 旨在解决使用Data Binding 相关的性能问题,因此不会对构建速度产生负面影响。
  • 语言(Languages): 支持Java和Kotlin

——————————————————————————————————

是时候做决定了

观察了所有方法及其分析,View Binding是目前可使用的最佳方法。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值