匿名Kotlin监听器内未解决的引用

Dr.*_*tix 6 android text-to-speech kotlin

我有下面的代码.这是Kotlin.知道为什么textToSpeech来自于textToSpeech.setLanguage(Locale.UK)告诉没有参考解决textToSpeech

val textToSpeech = TextToSpeech(
            applicationContext,
            object : TextToSpeech.OnInitListener {
                override fun onInit(status: Int) {
                    if (status == TextToSpeech.SUCCESS) {
                        textToSpeech.setLanguage(Locale.UK)
                    }
                }

            })
Run Code Online (Sandbox Code Playgroud)

起初我认为它是一个Idea kotlin插件bug,但似乎它实际上无法编译

hot*_*key 8

Kotlin已经强化了变量初始化策略,现在禁止在其初始化程序中引用变量,即使在lambdas和对象表达式中也是如此,这似乎是合理的:假设在变量赋值之前立即调用lambda.

对于您的情况,我可以建议在这个非常麻烦的构造中使用对象表达式作为解决方法:

val textToSpeech = object {
    val value: TextToSpeech get() = inner
    private val inner = TextToSpeech(
            applicationContext,
            { value.setLanguage(Locale.UK) }
    )
}.value
Run Code Online (Sandbox Code Playgroud)

这将使用可inner通过value属性接受的内部初始化匿名对象.请注意,inner初始化程序使用value属性.然后value提取并可以使用.

但请记住,这个技巧是不安全的:在运行时,使用valuebefore inner指定(例如在TextToSpeech构造函数中)将抛出NullPointerException.

此外,我已经OnInitListener使用SAM转换将lambda 替换为short,但是仍然可以在那里使用对象表达式.


UPD:检查这个问题,以便我总结这种方法.使用它,你可以写

val textToSpeech = selfReference {
    TextToSpeech(
        applicationContext,
        { self.setLanguage(Locale.UK) }
    )
}
Run Code Online (Sandbox Code Playgroud)

查看Github上消息来源.