【问题标题】:Android Studio - Korlin Coroutines --> Unresolved references: async & launchAndroid Studio - Korlin Coroutines --> 未解决的参考:异步和启动
【发布时间】:2021-04-24 18:18:41
【问题描述】:

我正在学习 Kotlin,我正在使用 Coroutines。

我在网上搜索,也许我使用的方法是旧的?但我有异步和启动(UI)没有解决......

我的 build.gradle:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}

kotlin {
    experimental {
        coroutines 'enable'
    }
}
...
dependencies {

    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'org.jetbrains.kotlin:kotlin-serialization'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
    implementation 'org.jetbrains.anko:anko-commons:0.10.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

从 api 获取数据的代码(已更新)

//getting data from api
fun fetchCharacterData(): Deferred<CharachterGenerator.CharacterData> {
    CoroutineScope(Main).launch {
        
           async {   val apiData = URL(CHARACTER_DATA_API).readText()
               CharachterGenerator.fromApiData(apiData)
           }
    }
       return <--- how to get this correct, what should I return?
}

我在按钮 setOnClickListener 中使用启动

generateButton.setOnClickListener {
            CoroutineScope(Main).launch {
            characterData = fetchCharacterData().await() 
            displayCharacterData()
            }
          }
        displayCharacterData()
    }

请跟我一起学习,我还在学习......

【问题讨论】:

    标签: android-studio kotlin kotlin-coroutines


    【解决方案1】:

    launchasync 是 CoroutineScope 的成员函数。除非您从实现 CoroutineScope 的类中调用它们,否则您不能对它们进行裸调用。您可能已经在 Kotlin 文档中看到了这一点,但他们的大多数示例都在 runBlocking lambda 中使用,它提供了一个作为函数接收器的作用域。在 Android 上,您通常会使用提供给您的 CorotuineScopes,例如 lifecycleScopeviewModelScope

    更新后编辑:

    异步执行某些操作并返回结果的函数的常见模式不是返回 Deferred,而是使其成为直接使用 withContext 返回结果的挂起函数:

    suspend fun fetchCharacterData() = withContext(Dispatchers.IO) {
        val apiData = URL(CHARACTER_DATA_API).readText()
        CharachterGenerator.fromApiData(apiData)
    }
    

    然后,当您调用它时,您的代码非常简单,因为您不必担心您在哪个调度程序上:

    generateButton.setOnClickListener {
        lifecycleScope.launch {
            characterData = fetchCharacterData()
            displayCharacterData()
        }
    }
    

    使用CoroutineScope() 类似构造函数的函数来创建一次性作用域是错误的,您没有将其存储在可以管理其生命周期的属性中。由于 Android 为您提供了 lifecycleScopeviewModelScope 并代表您管理它们的生命周期,因此您应该很少需要自己创建。

    【讨论】:

    • 我更新了我的答案。但是,打开一个新问题比更改原来的问题要好,因为现在可能有相同问题的其他人无法再搜索它。
    【解决方案2】:

    在浏览了其他几个文档后,我设法做到了这一点

    使用异步调用 API:

     fun fetchCharacterData(): Deferred<CharachterGenerator.CharacterData> {
    
        return CoroutineScope(IO).async  { val apiData = URL(CHARACTER_DATA_API).readText()
                   CharachterGenerator.fromApiData(apiData)
               }
        }
    
    

    发出请求并获得结果,然后将其发送以显示

            generateButton.setOnClickListener {
                CoroutineScope(Main).launch {
                    characterData = fetchCharacterData().await()
                    displayCharacterData()
                }
            }
    

    【讨论】:

    • 为什么要从我的答案中更改它?使用一次性CoroutineScopes 是不正确的。如果您的 Activity 在工作时关闭,则 Activity 将被泄露。 Here's an article 由 Kotlin 协程的首席开发人员提供,其中他专门提供了一个执行此操作的函数示例,并将其命名为 doNotDoThis()。没有理由创建单独的协程范围并将它们丢弃而不是使用现有的lifecycleScope。返回一个 Deferred 而不是简单地使其成为一个挂起函数也很奇怪。
    • @Tenfour04 请不要冒犯......我试图让他们都检查,似乎我只能检查一个......你的观点是正确的。唯一的问题是我没有在 IntelliJ 中找到可用的 android 协程,我只想要 Kotlin 的答案,而不是 android ......无论如何,谢谢你的评论和链接。我会标记你的答案...
    • 没有冒犯。我只是不希望任何人错误地使用协程。如果您不是为 Android 开发,则 Swing 和 JavaFX 有单独的协程后端,可提供所需的 CoroutineScope。如果你没有这个,你仍然应该在一个属性中设置你的 CoroutineScope,这样你就可以在生命周期中的适当位置取消它。
    猜你喜欢
    • 1970-01-01
    • 2021-11-05
    • 2020-01-05
    • 1970-01-01
    • 2019-12-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 2019-06-14
    相关资源
    最近更新 更多