本文记录了使用kotlin android extions时遇到的小问题以及对应的解决方法。
Kotlin Android Extensions
Kotlin Android Extensions 是用于Kotlin android开发的插件。
1 |
apply plugin: 'kotlin-android-extensions' |
借助该插件我们在Kotlin代码中不必再使用
findViewById()
,直接通过view id访问相应View即可。例如:
1 |
import kotlinx.android.synthetic.main.activity_main.* |
对Java代码中繁琐的
findViewById()
方便许多,对吧。
更多用法可以参考 这篇文章 。
遇到的问题
很不幸,使用 Kotlin Android Extensions 时遇到一个奇怪的问题。布局和代码如下:
activity_main.xml
1 |
|
content_main_clip.xml
1 |
|
MainActivity.kt
1 |
class MainActivity : AppCompatActivity() { |
代码功能:点击
btn_clip_demo
后,将
content_main_clip
中的内容(其中有一个id为
iv_demo
的ImageView)重新添加到
fl_container
,并且将
iv_demo
设置为红色。
问题描述:第一次点击
btn_clip_demo
,
iv_demo
被设置成红色。
但之后再点击btn_clip_demo,iv_demo没有被设置成红色
。
问题分析
Android Studio查看Kotlin对应Java代码的方式: Tools -> Kotlin -> Show Kotlin Bytecode -> Decompile
上述kotlin代码对应的Java代码如下:
1 |
public final class MainActivity extends AppCompatActivity { |
高大上的Kotlin Android Extensions生成的代码其实非常简单,要点如下:
1 |
btn_clip_demo.setOnClickListener { |
对照代码不难理解问题的原因在于:
第一次点击
btn_clip_demo
时,view cache策略并不生效,所以一切正常。第二次点击
btn_clip_demo
时,view cache策略生效。但view cache策略对我们的场景是错误的(从另一角度讲,可能是我的用法有误?)。从view cache中拿到的
iv_demo
对象是旧的。关键是,它已经从屏幕上移除,是不可见的。我们给它设置红色当然不起作用!而
inflate()
操作新添加到布局中的、在屏幕上可见的那个
iv_demo
,实际上被我们晾在一边。
所以这里我们不得不使用
findViewById
来获取那个被晾在一边的新的
iv_demo
。以下是修改后的代码:
1 |
btn_clip_demo.setOnClickListener { |
这回,无论我们如何点击按钮,
iv_demo
永远会被正确地设置为红色。