Каков наилучший способ объявить компонент UI в Android с Kotlin?
Я пытаюсь создать приложение для Android с помощью Kotlin в первый раз.
Я хочу объявить некоторые кнопки вне метода OnCreate, и я могу их инициализировать только внутри этой функции с помощью findViewById.
Могу ли я объявить простой и чистый код, например, в java?
private Button btnProceed;
Потому что при преобразовании его в Kotlin это выглядит так:
private var btnProceed: Button? = null
И тогда, когда нужно инициализировать функцию OnClick, нужно добавить! знак:
btnProceed!!.setOnClickListener
Каков правильный и самый чистый способ?
Ответы
Ответ 1
Это хороший прецедент для lateinit
. Маркировка свойства lateinit
позволяет сделать его недействительным, но не назначать ему значение в момент вызова конструктора Activity. Это там точно для таких классов, как "Действия", когда инициализация происходит в отдельном методе инициализации, позже запускаемого конструктора (в данном случае onCreate
).
private lateinit var btnProceed: Button
Если свойство считывается до того, как ему присвоено реальное значение, он будет генерировать исключение во время выполнения - используя lateinit
, вы берете на себя ответственность за его инициализацию перед тем, как вы впервые получите доступ к ней.
В противном случае, если вы хотите, чтобы компилятор гарантировал вам безопасный доступ, вы можете сделать значение Button
нулевым, как это делает конвертер по умолчанию. Вместо небезопасного !!
, который часто использует конвертер, вы должны использовать оператор безопасного вызова, в котором вы получаете доступ к свойству:
btnProceed?.setOnClickListener { ... }
Это приведет к регулярному вызову, если btnProceed
является ненулевым значением и ничего не делает.
В заключение вы можете проверить Kotlin Android Extensions, что избавляет от необходимости создавать свойства для вашего View
вообще, если он работает для вашего проекта.
Последнее редактирование (на данный момент): вы также должны посмотреть на использование lazy
, как описано в other
answers
. Быть ленивым - это круто.
Ответ 2
Вместо использования lateinit
вы также можете сделать ленивую инициализацию:
private val button by lazy {
findViewById(R.id.button) as Button
}
При первом обращении к свойству button
он будет выполнять блок один раз и использовать результат для будущих вызовов. Например, в onCreate
вы можете напрямую получить к нему доступ:
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(bundle)
setContentView(R.layout.my_view)
button.setOnClickListener { ... }
}
Ответ 3
Вы можете сделать это с помощью lateinit
, поскольку @zsmb13 предлагает, но это имеет тот недостаток, что ваши представления будут переменными, а не final. Если вы хотите, чтобы они были окончательными, вы можете использовать lazy
делегирование свойств
Используя lazy
, вы можете объявить, как значение будет инициализировано при первом попытке получить к нему доступ, объявив
private val btnProceed: Button by lazy {
findViewById(R.id.yourID)
}
Всякий раз, когда вы получаете доступ к btnProceed
, вы будете загружать свою активность (этот пример предполагает, что вы используете активность), чтобы вы могли использовать этот метод