使用Kotlin在Android上的UI组件上声明的最佳方法是什么?

Udi*_*Udi 13 java android kotlin

我正在尝试首次使用Kotlin构建Android应用程序.

我想在OnCreate方法之外的一些按钮上声明,我只能用findViewById在这个函数内初始化它们.

我可以在java中简单而干净的代码中声明吗?

private Button btnProceed;
Run Code Online (Sandbox Code Playgroud)

因为在将其转换为Kotlin时,它看起来像:

private var btnProceed: Button? = null
Run Code Online (Sandbox Code Playgroud)

然后在初始化OnClick函数时需要添加!标志:

btnProceed!!.setOnClickListener
Run Code Online (Sandbox Code Playgroud)

什么是正确和最干净的方式?

zsm*_*b13 21

这是一个很好的用例lateinit.标记属性lateinit允许您使其不可为空,但在调用Activity的构造函数时不为其赋值.它恰好适用于像Activities这样的类,当初始化发生在单独的初始化方法中时,晚于正在运行的构造函数(在本例中onCreate).

private lateinit var btnProceed: Button
Run Code Online (Sandbox Code Playgroud)

如果在为其分配实际值之前读取属性,它将在运行时抛出异常 - 通过使用lateinit,您将在首次访问它之前负责初始化它.


否则,如果您希望编译器保证为您提供安全访问,则可以Button在转换器默认情况下使其为可空.而不是转换器经常使用的不安全!!操作符,您应该使用安全调用操作符来访问该属性:

btnProceed?.setOnClickListener { ... }
Run Code Online (Sandbox Code Playgroud)

如果btnProceed是非空值,这将进行常规调用,否则不执行任何操作.


最后,您可以查看Kotlin Android ExtensionsView,如果它适用于您的项目,则无需为您的s 创建属性.


上次编辑(暂时):您还应该lazy按照中所述使用.懒惰很酷.other answers


nha*_*man 11

lateinit您也可以进行延迟初始化,而不是使用它:

private val button by lazy {
    findViewById(R.id.button) as Button
}
Run Code Online (Sandbox Code Playgroud)

第一次访问该button属性时,它将执行一次块并将结果用于将来的调用.在onCreate比如,你现在可以直接访问它:

fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(bundle)
  setContentView(R.layout.my_view)

  button.setOnClickListener { ... }
}
Run Code Online (Sandbox Code Playgroud)

  • 这可能会导致碎片中的内存泄漏。https://www.bignerdranch.com/blog/kotlin-when-to-use-lazy-or-lateinit/ (2认同)