Kotlin 不再使用 findViewById 的原理探析

使用过 Kotlin 的都知道, Kotlin 一个非常棒的特性是:可以在 .kt 文件中直接使用控件的 ID 对控件进行操作。而 Java 代码中,需要像先式声明控件,再使用 findViewById() 来找到控件,然后才能操作该控件。该特性称为Static Layout Import,即静态布局引入。

举个栗子,假设某个 activity 的 xml 文件: activity_main.xml 中有个 TextView 控件,其 ID 定为 tv_name ,在对应的 .kt 文件中将布局如下引入进来后:

import kotlinx.android.synthetic.main.activity_main.*

就可以直接使用其ID tv_name来操作这个 TextView 控件了:
在这里插入图片描述

可以看到,利用我们在 xml 中 定义的 ID tv_name,就可以直接使用该 TextView 的 text、textSize 等属性或方法,甚至比著名的第三方开源库 ButterKnife还要方便简洁。妥妥的黑科技有木有,大道至简~~
ps:text / textSize 等属性其实是 Kotlin 扩展属性,通过反编译查看底层的 Java 代码,可以发现其实还是使用其对应的 setter 方法,即setText()/setTextSize()。

那么问题来了,Kotlin 可以直接使用控件 ID 来操作控件,是如何做到的呢?

我们先将 Kotlin 代码转换为对应 Java 代码。

在 Android Studio 中,点击最顶部的 Tools -> Kotlin,然后选择 Show Kotlin Bytecode,可以在右侧面板中看到对应的字节码,然后点击 Decompile ,就可以查看 Kotlin 代码对应的 Java 代码:
在这里插入图片描述

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

在这里插入图片描述

通过反编译后的代码,可以看到这个黑科技的原理就一目了然了 。Kotlin 会自动生成类似 findViewById() 的方法:findCachedViewById(),在这个方法里面创建一个 HashMap 来缓存每次查找到的 View,避免每次调用 View 的属性或方法时都会重新调用findCachedViewById()进行查找。具体查找流程是这样的:在findCachedViewById()中,会先通过缓存 HashMap 的 get 方法来获取控件, get() 中传入的 key 即控件 ID,由于第一次 get 的值为 null ,因此会调用findViewById() ,并把控件 ID作为 key 和 找到的控件 View 作为 value ,put 进 HashMap 缓存中,这样,第二次再使用该控件 ID 的时候,就直接可以从 HashMap 中获取到了。很简单吧。

以上就是在 activity 中里面直接使用控件 ID 的原理分析。

但是在 fragment 里面使用就需要注意了,不要在onCreateView方法里用 view 的 ID,而是在 onViewCreated以后使用,否则可能会由于找不到控件而出现空指针异常的问题。正确的姿势是这样的:
在这里插入图片描述

同样,将上述 Kotlin 代码转化为对应的 Java 代码:
在这里插入图片描述

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

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

通过以上探究,Kotlin 中可以不再使用 findViewById、而是直接使用控件 ID 来操作控件 的原理就分析完啦。

总结:

  • Kotlin 可以直接使用 id 来操作控件的原因是其底层做了类似 findViewById 的转换来找到对应的控件,并且找到后会缓存起来;
  • fragment 中不要在onCreateView方法里用 view 的 ID,而是应该在onViewCreated以后使用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin 中,可以使用 findViewById 来查找视图,但是 Kotlin 推荐使用属性委托来自动查找视图,而不需要使用 findViewById。 在使用属性委托时,需要使用 Kotlin Android Extensions 或者 View Binding。 1. Kotlin Android Extensions: Kotlin Android Extensions 是 Kotlin 提供的一个插件,它通过自动生成视图的属性来简化视图查找。 首先,在项目的 build.gradle 文件中添加以下依赖: ```kotlin android { ... androidExtensions { experimental = true } } ``` 然后,在布局文件中定义一个 id: ```xml <TextView android:id="@+id/myTextView" ... /> ``` 最后,在 Kotlin 代码中就可以直接使用该视图的属性了: ```kotlin import kotlinx.android.synthetic.main.activity_main.* // 在 Activity 中 myTextView.text = "Hello, Kotlin Android Extensions!" // 在 Fragment 中 view.myTextView.text = "Hello, Kotlin Android Extensions!" ``` 2. View Binding: View Binding 是 Android Jetpack 提供的一种类型安全的视图查找方式。 首先,在项目的 build.gradle 文件中启用 View Binding: ```kotlin android { ... viewBinding { enabled = true } } ``` 然后,在布局文件中定义一个 id: ```xml <TextView android:id="@+id/myTextView" ... /> ``` 最后,在 Kotlin 代码中使用 View Binding 来查找视图: ```kotlin import com.example.myapp.databinding.ActivityMainBinding // 在 Activity 中 val binding = ActivityMainBinding.inflate(layoutInflater) binding.myTextView.text = "Hello, View Binding!" // 在 Fragment 中 val binding = FragmentMainBinding.bind(view) binding.myTextView.text = "Hello, View Binding!" ``` 这些是在 Kotlin 中查找视图的常用方法,可以根据个人偏好选择其中一种方式来使用

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值