#android #kotlin
#Android #kotlin
Вопрос:
Я новичок в Android. Вот код:
Switch.setOnCheckedChangeListener { _, isChecked ->
// do something}
Я сделал некоторое кодирование на C , поэтому я знаю, что должен вызывать его следующим образом
variable = OnCheckedChangeListener
Switch.setOnCheckedChangeListener**(variable)** { _, isChecked ->
// do something}
Я не знаю, почему функция работает без моего ввода каких-либо аргументов.
Большое вам спасибо.
Комментарии:
1. Вы передаете аргумент.
{ _, isChecked -> ... }
Часть является аргументом в форме лямбда-выражения.2. Я проследил эту странную иерархию наследования. Не могли бы вы сказать мне, прав ли я. setOnCheckedChangeListener требует OnCheckedChangeListener в качестве своего параметра. OnCheckedChangeListener — это интерфейс, который на самом деле является просто функцией. В итоге вы передаете эту функцию в качестве аргумента setOnCheckedChangeListener.
3. «OnCheckedChangeListener — это интерфейс, который на самом деле является просто функцией» — не совсем, но вы близки.
OnCheckedChangeListener
имеет единственную абстрактную функцию в определении интерфейса. Kotlin поддерживает создание экземпляров такого интерфейса из лямбда-выражения или другого типа функции .
Ответ №1:
Если мы посмотрим на исходный код для Switch
представления, setOnCheckedChangeListener()
метод определяется следующим образом:
fun setOnCheckedChangeListener(listener: CompoundButton.OnCheckedChangeListener?) {
mOnCheckedChangeListener = listener
}
Он ожидает аргумент в виде интерфейса OnCheckedChangeListener
, определение которого выглядит следующим образом:
interface OnCheckedChangeListener {
fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean)
}
У него есть только один метод. Интерфейс только с одним абстрактным методом называется функциональным интерфейсом или интерфейсом с одним абстрактным методом (SAM).
Для функциональных интерфейсов вы можете использовать преобразования SAM, которые помогают сделать ваш код более кратким и читаемым с помощью лямбда-выражений.
Вместо создания класса, который реализует функциональный интерфейс вручную, вы можете использовать лямбда-выражение. С помощью преобразования SAM Kotlin может преобразовать любое лямбда-выражение, сигнатура которого совпадает с сигнатурой единственного метода интерфейса, в экземпляр класса, который реализует интерфейс.
Итак, причина, по которой вам не нужно передавать экземпляр OnCheckedChangeListener
, заключается в том, что из-за синтаксического сахара Kotlin позволяет вам просто определить тело метода, который описывается интерфейсом, и он создаст и передаст аргумент за кулисами.
Если бы вы хотели сделать это самостоятельно, это выглядело бы так:
switch.setOnCheckedChangeListener(object : OnCheckedChangeListener {
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
// do something
}
})
Комментарии:
1. Большое вам спасибо. Это лучший ответ, потому что вы подробно рассказали о том, что на самом деле происходит под капотом с вашим последним фрагментом кода. Большинство книг для начинающих, обучающих программированию на Android, не вдаются в этот уровень детализации. Они думают, что новички все Энштейны.