在添加 "run" 之前,Lambda 将被忽略

Lambda's are ignored until "run" is added

我有一个通过 Retrofit 调用 API 的 rx 链。我使用标准 rx subscribe({...}) 方法订阅了我的 API 服务,并向它传递了一个 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")
                }

            })

查看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")
        }

{ 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")
    }
}