kotlin中mainactivity无法直接调用xml中的控件_Kotlin甩掉findViewbyId,原理几何

在Kotlin中,一个非常好用的特性是:可以直接使用控件 ID 对控件进行操作,而不需要像 Java 中那样先声明控件,使用 findViewById() 来找到控件,然后才能操作该控件。该特性称为Static Layout Import,即静态布局引入。

举个栗子, activity_main.xml中有个TextView,其 ID 为 tv_name 的,将布局像下面这样引入进来后: 

4aa0723e7a2db1a43f62bf86014761d5.png

就可以直接使用 tv_name: 

5336611547ac780f2b060fde41c7292f.png

可以看到,利用tv_name可以直接使用该 TextView 的 text、textSize 等属性或方法,甚至比著名的开源库 ButterKnife 还简洁。

ps:text / textSize 等属性其实是 Kotlin 扩展属性,反编译查看底层的 Java 代码可以发现其实还是使用其对应的 setter 方法。

那么为什么可以直接使用控件 ID 来操作控件呢?我们先将 Kotlin 转为 Java 代码。在 Android Studio 中,点击最顶部的 Tools -> Kotlin ,然后选择 Show Kotlin Bytecode,可以在右侧面板中看到对应的字节码,然后点击 Decompile ,就可以查看 Kotlin代码对应的 Java 代码: 

c540b9cd26074a237993e5dfb72748aa.png

可以发现,tv_name 部分的代码对应的 Java 代码如下: 

ef7c0ad3079c9cb9bba2758827d47ce3.png

反编译后可知,这种用法的原理是 Kotlin 会自动生成类似 findViewById() 的方法:findCachedViewById(),在这个方法里面创建一个 HashMap 缓存每次查找到的 View,避免每次调用 View 的属性或方法时都会重新调用findCachedViewById()进行查找。

具体查找流程是这样的:在findCachedViewById()中,会先通过缓存 HashMap 的 get 方法来获取控件, get() 中传入的 key 即控件 ID,由于第一次 get 的值为 null ,因此会调用findViewById() ,并把控件 ID作为 key 和找到的控件 View 作为 value put 进缓存 Map 中。这样,第二次再使用该控件 ID 的时候,就直接可以从 Map 中获取到了。还是挺好理解的吧。

以上是在 activity 里面直接使用控件 ID,但是在 fragment 里面使用要注意的是,不能在onCreateView方法里用 view 的 ID,而是在 onViewCreated 以后使用,不然可能会由于找不到控件而出现空指针异常的问题。正确的用法是这样的: 

d45ba72f2cc416e1a14618b39e24272c.png

再将上述 Kotlin 代码转化为对应的 Java 代码: 

905e6e2dfa63f188263033142d5c83d6.png

可以看到, fragment 里面跟前面的基本原理类似,同样也是在findCachedViewById()中创建缓存 Map,区别在于 fragment 里面是通过getView()来 findViewById()的,如果是在 onCreateView 方法里使用控件 ID,这个时候getView()会返回 null,即 var10000 为 null,这样 findCachedViewById() 就返回空了。

因此,千万要注意fragment里面不能在onCreateView方法里用view的ID。

好了,Kotlin 中不再使用 findViewById,而是直接使用控件 ID 来操作控件的原理就说到这里。

----------  END  ----------

*本文转载自Android机动车,感谢授权

本文观点不代表我方观点

9fcc59e60d6ad6af348f606162c9fb6e.gif

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值