我有一个通过Retrofit调用API的rx链。我订阅了我的API服务,使用标准的rx subscribe({...})
方法并将lambda传递给它。不幸的是,当我的调用最终完成时,我在lambda中执行的所有代码都被完全忽略了。 AndroidStudio提出了一个修复方法,它基本上为我的lamda添加了一个内联函数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")
}
})
答案 0 :(得分: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")
}
}
创建一个lambda表达式,并且不执行任何操作。
你想做的是
{ 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")
}
}
答案 1 :(得分:1)
查看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
方法创建内联属性:
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为具有最后一个参数的lambda的函数提供了更好的语法。如果我写这篇文章,我会用你所写的等价语法编写以下代码:
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")
}