标签: kotlin-coroutines

在协程中并行运行两个 Kotlin 协程

我有两个挂起功能:

suspend fun sendData() : Boolean 

suspend fun awaitAcknowledge() : Boolean
Run Code Online (Sandbox Code Playgroud)

我想将它们包装在第三个挂起函数中,它们应该在其中并行执行,并且我想通过具有两个返回值来计算最终结果:

suspend fun sendDataAndAwaitAcknowledge() : Boolean {
    // TODO execute both in parallel and compare both results
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我这样写的话,

suspend fun sendDataAndAwaitAcknowledge() : Boolean {
    val sendResult = sendData()
    val receiveAck = awaitAcknowledge()
}
Run Code Online (Sandbox Code Playgroud)

这些函数将按串行顺序执行,这在我的情况下不起作用。

来自 RxJava,我想实现类似zip操作符的功能:

Single.zip(awaitAcknowledge(), sendData(), {receiveAck, sendResult -> ...})
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点Coroutines

android kotlin kotlin-coroutines

21
推荐指数
2
解决办法
9601
查看次数

Kotlin Flow:为什么函数 merge() 最多只能接受 5 个流的参数

我注意到,combine() 函数最多只能接受 5 个流的参数

public fun <T1, T2, T3, T4, T5, R> combine(
    flow: Flow<T1>,
    flow2: Flow<T2>,
    flow3: Flow<T3>,
    flow4: Flow<T4>,
    flow5: Flow<T5>,
    transform: suspend (T1, T2, T3, T4, T5) -> R
): Flow<R> = combineUnsafe(flow, flow2, flow3, flow4, flow5) { args: Array<*> ->
    transform(
        args[0] as T1,
        args[1] as T2,
        args[2] as T3,
        args[3] as T4,
        args[4] as T5
    )
}
Run Code Online (Sandbox Code Playgroud)

这背后有什么特殊原因吗?(或者可能不是?)

如果我在本地文件中定义一个有6个参数的combine(),例如

private fun <T1, T2, T3, T4, T5, T6, R> combine(
    flow: Flow<T1>,
    flow2: Flow<T2>,
    flow3: Flow<T3>, …
Run Code Online (Sandbox Code Playgroud)

coroutine kotlin kotlin-coroutines kotlin-flow

21
推荐指数
2
解决办法
5261
查看次数

从多个状态流收集

我的 viewModel 中有 2 个 stateFlow。为了将它们收集到片段中,我必须启动协程两次,如下所示:

    lifecycleScope.launchWhenStarted {
        stocksVM.quotes.collect {
            if (it is Resource.Success) {
                it.data?.let { list ->
                    quoteAdapter.submitData(list)
                }
            }
        }
    }

    lifecycleScope.launchWhenStarted {
        stocksVM.stockUpdate.collect {
            log(it.data?.data.toString())
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果我有更多的 stateFlow,我必须分别启动协程。有没有更好的方法来处理我的片段/活动或其他地方的多个 stateFlow?

android kotlin kotlin-coroutines kotlin-stateflow

21
推荐指数
4
解决办法
1万
查看次数

如何停止或取消 Kotlin 协程(立即停止当前运行的代码块)?

我想实现什么目标?

我有一个下载图像的任务,但随着屏幕滚动,它将取消以前的下载并开始下载新的图像。我希望当它取消coroutine下载上一个图像时,它会立即停止并释放bandwidth新图像,以便更快地下载。

我已经尝试过什么?

我尝试了多种方法来停止,coroutine但即使在取消后,它仍然会继续进行,直到完成下载coroutine。当我取消它时,它会生成coroutine一个变量并停止调用进一步的挂起函数。但问题是,如果它运行多次或从该任务下载图像,除非完成,否则不会取消。Like 循环将完成其迭代,然后协程将被取消。isActivefalseloop1000000network1000000

我已经尝试过这些但没有成功:

job.cancel()
scope.cancel()
Run Code Online (Sandbox Code Playgroud)

我尝试了很多方法来实现这一目标,但没有找到解决方案。我现在无法在我的项目中使用任何库。

这个用例不是通过线程、执行器服务、协程来实现的。因为所有人的行为都是一样的。

更多类似的问题:

如何取消 kotlin 协程以进行阻塞下载操作

AsyncTask 不会取消 android 中长时间运行的操作

协程持有的服务泄漏

android coroutine kotlin kotlin-coroutines coroutinescope

21
推荐指数
2
解决办法
3万
查看次数

Flow 类不需要类型参数

我在使用 Kotlin Flow 时遇到了问题。

我从官方指南中复制了以下代码

fun simple(): Flow<Int> = flow { 
    for (i in 1..3) {
        delay(100) 
        emit(i) 
    }
}
Run Code Online (Sandbox Code Playgroud)

但Android Studio提示如下错误:

Flow 类不需要类型参数

我究竟做错了什么?

kotlin kotlin-coroutines kotlin-flow

21
推荐指数
1
解决办法
7678
查看次数

收到 kotlin 错误“等待 60000 毫秒后,测试协程未完成”

我是测试新手,试图获取第二个流量值并断言它,当我逐个运行此测试时运行良好,但是当我运行整个测试时,第一个测试运行良好,其余测试给我超时错误。

错误 :

After waiting for 60000 ms, the test coroutine is not completing
kotlinx.coroutines.test.UncompletedCoroutinesError: After waiting for 60000 ms, the test coroutine is not completing
    at app//kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTestCoroutine$3$3.invokeSuspend(TestBuilders.kt:304)
    (Coroutine boundary)
Run Code Online (Sandbox Code Playgroud)
@OptIn(ExperimentalCoroutinesApi::class)
class HomeViewModelTest {

    private lateinit var viewModel: HomeViewModel
    private val testDispatcher = UnconfinedTestDispatcher()

    @Before
    fun setup() {
        viewModel = HomeViewModel(FakeOrderRepository())
        Dispatchers.setMain(testDispatcher)
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
        testDispatcher.cancel()
    }

    @Test
    fun flowViewModelTesting1() = runTest {
        val result = viewModel.homeUiState.drop(1).first()
        assertThat(true).isTrue()
    }


    @Test
    fun flowViewModelTesting2() = runTest {
        val result …
Run Code Online (Sandbox Code Playgroud)

android kotlin kotlin-coroutines kotlin-flow

21
推荐指数
2
解决办法
1万
查看次数

未解决的参考:启动

试图为Kotlin协程运行一些示例,但无法构建我的项目。我正在使用最新的gradle版本-4.1

有什么建议要检查/修复吗?

这是 build.gradle

buildscript {
    ext.kotlin_version = '1.1.4-3'

    repositories {
        mavenCentral()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: 'kotlin'
apply plugin: 'application'

kotlin {
    repositories {
        jcenter()
    }

    experimental {
        coroutines 'enable'
    }

    dependencies {
        compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.18"
    }
}
Run Code Online (Sandbox Code Playgroud)

main.kt

fun main(args: Array<String>) {
    launch (CommonPool) {
        delay(1000L)
        println("World!")
    }

    println("Hello, ")
    Thread.sleep(2000L)
}
Run Code Online (Sandbox Code Playgroud)

当我跑步时,gradle compileKotlin我得到以下内容

e: /Users/philippgrigoryev/projects/kotlin-coroutines/src/main/kotlin/main.kt: (2, 5): Unresolved reference: launch
e: /Users/philippgrigoryev/projects/kotlin-coroutines/src/main/kotlin/main.kt: (2, 13): Unresolved reference: CommonPool
e: /Users/philippgrigoryev/projects/kotlin-coroutines/src/main/kotlin/main.kt: (3, 9): …
Run Code Online (Sandbox Code Playgroud)

gradle kotlin kotlin-coroutines

20
推荐指数
3
解决办法
7916
查看次数

现有的3函数回调Kotlin协同程序

我有一个具体例子的一般性问题:在拍照时,我想在Android中使用Kotlin协程魔法而不是回调地狱.

manager.openCamera(cameraId, object : CameraDevice.StateCallback() {
    override fun onOpened(openedCameraDevice: CameraDevice) {
        println("Camera onOpened")
        // even more callbacks with openedCameraDevice.createCaptureRequest()....
    }

    override fun onDisconnected(cameraDevice: CameraDevice) {
        println("Camera onDisconnected")
        cameraDevice.close()
    }
    ...
Run Code Online (Sandbox Code Playgroud)

我怎么把它转换成......错误......不那么难看的东西? 是否可以使用三个左右的函数进行平均回调,并通过将主流指定为promise-result路径将其转换为promise链? 如果是这样,我应该/我是否应该使用协同程序使其异步?

我喜欢async和.await会产生的东西

manager.open(cameraId).await().createCaptureRequest()
Run Code Online (Sandbox Code Playgroud)

我试图通过以下内容来做到这一点,但是...我不认为我正在使用CompletableDeferred!

suspend fun CameraManager.open(cameraId:String): CameraDevice {
    val response = CompletableDeferred<CameraDevice>()
    this.openCamera(cameraId, object : CameraDevice.StateCallback() {
        override fun onOpened(cameraDevice: CameraDevice) {
            println("camera onOpened $cameraDevice")
            response.complete(cameraDevice)
        }

        override fun onDisconnected(cameraDevice: CameraDevice) {
            response.completeExceptionally(Exception("Camera onDisconnected $cameraDevice"))
            cameraDevice.close()
        }

        override fun onError(cameraDevice: CameraDevice, error: Int) {
            response.completeExceptionally(Exception("Camera onError $cameraDevice …
Run Code Online (Sandbox Code Playgroud)

android kotlin kotlin-coroutines

20
推荐指数
2
解决办法
6335
查看次数

Android 和 Kotlin 协程:不适当的阻塞方法调用

我有以下课程:

class Repository(
    private val assetManager: AssetManager,
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) {
    suspend fun fetchHeritagesList(): HeritageResponse = withContext(ioDispatcher) {
        try {
            // TODO Blocking method call?
            val bufferReader = assetManager.open("heritages.json").bufferedReader()
...
Run Code Online (Sandbox Code Playgroud)

open("heritages.json")我想知道为什么我会在这句话中收到警告Innapropriate blocking method call?修复不是withContext(ioDispatcher)这样的吗?

感谢您的解释!

android kotlin kotlin-coroutines

20
推荐指数
1
解决办法
7058
查看次数

使用 rememberCoroutineScope() 与 LaunchedEffect

语境

在 Jetpack compose 中,我们可以选择使用rememberCoroutineScope()和使用LaunchedEffect可组合物以使用协程/运行挂起功能(显示小吃店等)。

到目前为止,我采用的约定是记住我的 compose 树顶部的单个协程作用域,并通过函数参数将其传递到需要它的地方。这似乎是一个很好的做法,但另一方面,它给我的函数签名增加了额外的噪音。

问题

  1. 是否有任何理由更喜欢使用LaunchedEffectoverrememberCoroutineScope()内部可组合函数?
  2. 是否值得为每个撰写树只创建/记住一次协程范围,还是应该只调用rememberCoroutineScope()实际启动协程的每个函数?

kotlin-coroutines android-jetpack-compose

20
推荐指数
3
解决办法
2009
查看次数