I have an rx chain that calls an API through Retrofit. I subscribe to my API service, with standard rx subscribe({...})
method and pass a lambda to it. Unfortunately when my call is finally completed, all the code I have added to be executed inside lambda is totally ignored. AndroidStudio suggested a fix which basically adds an inline function run
to my lamda and... it magically works. I have no idea what's happening. Why does it not work without run
? What does run
do?
The code follows:
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")
}
})
{ expressions }
is a short form of { -> expressions }
, which is a function literal with zero parameters.
Therefore,
{ data ->
{
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
}
is the same as
{ data ->
{ ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
}
which creates a lambda expression, and do nothing with it.
What you want to do is
{ data ->
{ ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}()
}
but this does the same as
{ data ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
plus additional function creation overhead.
run { ... }
is the same as { ... }()
minus additional temporary function creation overhead. So the above is the same as
{ data ->
run { ->
val cs = data.creditReportInfo.score
view.setCreditScore(cs)
Logger.getLogger("success:").info("credit score $cs")
}
}