Kotlin学习之消失的findViewById

刚使用 Kotlin 的时候,感觉到处都充满了惊喜,也处处充满了不习惯,但总体来说语法糖带来的快乐还是要远大于痛苦的,之前学习 Kotlin 一直是在代码里写写,没有涉及到 UI,因此今天需要使用控件,当习惯性的输入 findViewById 时发现编译器没有任何提示时就懵逼了,人间惨剧:消失不见的 findViewById 正式上演。。

在包含控件非常多的 Activity 或是 Fragment 中,经常会看到排排坐的 findViewById,虽然看着工整,但写起来的痛苦真的是谁写谁知道啊,虽然使用黄油刀可以来避免这一问题,但其实就代码而言是没有什么改变的,还是需要去重复的 @BindView
在一番Google大法后,我不禁喊出了一声卧槽,怎么在 Kotlin 中直接用 View 的 ID 就可以直接使用 View 了么???

使用

首先需要在App 的 build.gradle 中引入 kotlin-android-extensions 插件:

1
2
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

此时,假如有个 id 为 testTitle 的 TextView,想要使用它,只需要在对应的 Activity 或是 Fragment 中直接输入 ID 即可,就像使用成员变量一样方便,而完成这一步,需要引入下面这句:
import kotlinx.android.synthetic.main.activity_main.*
这个在输入 ID 时会被自动导入,因此不用自己手动去导入。

背后玄机

其实背后的奥秘,看一下反编译后的 Kotlin 代码就一目了然了,通过点击 Android Stuio 的 Tools –> Kotlin –> Show Kotlin Bytecode,可以看到编译期间对应 Kotlin 文件生成的 Java 代码,主要关注其中的 findCachedViewById 方法,在使用 ID 的地方,都其实是使用 findCachedViewById 来获取 View 的,而且还会在第一次获取到后,对 View 做一个缓存,保证了不会每次调用 ID 都去调用 findViewById

1
2
3
4
5
6
7
8
9
10
11
12
13
public View _$_findCachedViewById(int var1) {
if (this._$_findViewCache == null) {
this._$_findViewCache = new HashMap();
}

View var2 = (View)this._$_findViewCache.get(var1);
if (var2 == null) {
var2 = this.findViewById(var1);
this._$_findViewCache.put(var1, var2);
}

return var2;
}

参考

Kotlin Android Extensions: Say goodbye to findViewById