Преобразование Kotlin SAM не работает для функции с двумя аргументами - PullRequest
0 голосов
/ 02 декабря 2018

Я изучаю Kotlin и пытаюсь использовать LiveData с ним.Поскольку библиотека LiveData написана на Java, Kotlin должен поддерживать преобразования SAM.

LiveData класс имеет метод observe с двумя аргументами, Observer и LifecycleOwner:

void observe (LifecycleOwner owner, Observer<T> observer)

Оба являются интерфейсами с одним методом.Когда я использую лямбду SAM для обоих аргументов, она работает нормально:

val liveData = MutableLiveData<Int>()
liveData.observe({ lifecycleOwner.lifecycle }, { invokeMyMethod(it) })

Также она работает, когда я предоставляю объект и лямбда SAM с определенным типом (Observer):

val liveData = MutableLiveData<Int>()
liveData.observe(lifecycleOwner, Observer { invokeMyMethod(it) })

Однако, когда я пытаюсь использовать объект для одного аргумента и SAM лямбда без типа для другого аргумента:

val liveData = MutableLiveData<Int>()
liveData.observe(lifecycleOwner, { invokeMyMethod(it) })

, это дает мне ошибку компиляции.Но почему я не могу написать такой код?Это именно то, что я хочу, компактный и без шаблонного кода.В LiveData есть только один метод observe, поэтому я должен указать тип лямбды?

Компилятор выдает такую ​​ошибку:

Несоответствие типов.Требуется: Наблюдатель!>, Найдено: () → Юнит

Небольшое обновление, я только что проверил эту комбинацию, и она также не работает:

val liveData = MutableLiveData<Int>()
liveData.observe({ lifecycleOwner.lifecycle }, Observer { invokeMyMethod(it) })

Итакработает, когда оба аргумента являются лямбда-выражениями SAM, но не работает, когда один - лямбда-SAM, а другой - лямбда-SAM с указанным типом.В этом случае компилятор также выдает ту же ошибку Type mismatch.

Ответы [ 2 ]

0 голосов
/ 02 декабря 2018

Это https://youtrack.jetbrains.com/issue/KT-14984. И, в соответствии с этим, оно должно быть окончательно исправлено в Kotlin 1.3, но необходимые изменения в типовых выводах уже включены и должны быть явно включены: https://discuss.kotlinlang.org/t/new-type-inference-in-kotlin-1-3-0-rc-190/9914/2

0 голосов
/ 02 декабря 2018

Ваше наблюдение кажется правильным, но я не смогу вам ответить, почему.

options

Мы видим, что Котлин видит либо LifecycleOwner, Observer или () -> Lifecycle, (Int?) -> Unit.Что касается того, почему вы не видите один с каждой комбинацией , только люди, работающие на Kotlin, будут знать!


Однако я смогу дать вам обходной путь.

Добавьте эту функцию расширения в ваш проект:

inline fun <T> LiveData<T>.observe(lifecycleOwner: LifecycleOwner, crossinline observer: (T?) -> Unit) {
    observe(lifecycleOwner, Observer { observer(it) })
}

И теперь она будет работать волшебным образом (при условии, что ваша функция расширения импортирована)!

fun blah() {
    liveData.observe(lifecycleOwner) { // <-- trailing lambda
        invokeMyMethod(it)
    }
}
...