Лямбда игнорируются до тех пор, пока не будет добавлено "run"
У меня есть цепочка RX, которая вызывает API через Retrofit. Я подписываюсь на мой сервис API со стандартным rx subscribe({...})
метод и передать лямбду к нему. К сожалению, когда мой вызов, наконец, завершен, весь код, который я добавил для выполнения внутри лямбды, полностью игнорируется. AndroidStudio предложила исправление, которое в основном добавляет встроенную функцию run
к моей лямде и... это волшебно работает. Я понятия не имею, что происходит. Почему это не работает без run
? Что значит run
делать?
Код следует:
valuesServiceApi.getValues()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ data ->
run { //<- What's this?
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
})
2 ответа
{ expressions }
это короткая форма { -> expressions }
, который является литералом функции с нулевыми параметрами.
Следовательно,
{ data ->
{
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
}
такой же как
{ data ->
{ ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
}
который создает лямбда-выражение, и ничего не делать с ним.
Что вы хотите сделать, это
{ data ->
{ ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}()
}
но это так же, как
{ data ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
плюс дополнительные затраты на создание функций.
run { ... }
такой же как { ... }()
минус дополнительная временная функция создания накладных расходов. Таким образом, выше, так же, как
{ data ->
run { ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
}
Посмотрите на определение run
функция. Это простая встроенная функция, которая практически ничего не делает. Я использую это, чтобы отделить мою логику в Kotlin.
val runResult = run { //
// Do something in here that doesn't impact the rest of my algorithm / code
val a = 1
val b = 2
a + b // return a + b
}
// Can't access a or b here. run successfully keeps the rest of my algorithm separate / clean
Вы также можете использовать run
Метод для создания свойства inline:
class Example {
/**
* Will have the value "0123456789"
*/
val exampleString: String = run { //
val sb = StringBuilder()
for (i in 0..9) {
sb.append(i)
}
sb.toString()
}
}
Теперь, как говорится, run
определенно не влияет на ваш код RxJava вообще. Я рекомендую вам очистить ваш проект и запустить его снова. Кроме того, kotlin предлагает более приятный синтаксис для функций, которые имеют лямбду для последнего параметра. Если бы я писал это, я написал бы следующий код с эквивалентным синтаксисом того, что вы написали:
valuesServiceApi.getValues()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { data ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}