标签: kotlinx.coroutines

在 kotlin 中,如何模拟包装回调的挂起函数?

假设有一个带有回调的接口:

interface SomeInterface {
    fun doSomething(arg: String, callback: (Exception?, Long) -> Unit)
}
Run Code Online (Sandbox Code Playgroud)

我将其扩展为这样的挂起函数:

suspend fun SomeInterface.doSomething(arg: String): Long = suspendCoroutine { cont ->
    this.doSomething(arg) { err, result ->
        if (err == null) {
            cont.resume(result)
        } else {
            cont.resumeWithException(err)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想在测试中模拟这个,但失败了。理想情况下,我想使用这样的东西:

@Test
fun checkService() {
    runBlocking {
        val myService = mock<SomeInterface>()
        whenever(myService.doSomething(anyString())).thenReturn(1234L)
        val result = myService.doSomething("")
        assertEquals(result, 1234L)
    }
}
Run Code Online (Sandbox Code Playgroud)

上述语法因模拟异常而失败,因为它期望回调的匹配器。

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
Run Code Online (Sandbox Code Playgroud)

我怎样才能模拟这样的挂起功能?如果无法使用类似的语法,我如何才能使用所需的参数进行模拟回调,以便在整个代码中使用的挂起变体在测试期间返回所需的结果?

更新:当它是一个扩展功能时,它似乎是不可能的。根据Marko Topolnik的评论,我认为这是因为扩展只是一个静态函数,它超出了 …

mocking callback mockito kotlin kotlinx.coroutines

10
推荐指数
2
解决办法
4276
查看次数

编译错误:"-Xcoroutines无效:无论如何在1.3及更高版本中都启用了协同程序"

当我尝试编译用Kotlin编写的Android应用程序时,我收到以下编译错误,并且我的构建失败:

w: -Xcoroutines has no effect: coroutines are enabled anyway in 1.3 and beyond
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题?

compiler-errors gradle kotlin android-studio kotlinx.coroutines

10
推荐指数
2
解决办法
1770
查看次数

什么是CoroutineScope背后的概念?

在阅读了CoroutineScope的介绍和javadoc后,我仍然有点混淆了背后的想法CoroutineScope是什么.

文档的第一句"定义新协程的范围".我不清楚:为什么我的协同程序需要一个范围?

另外,为什么单独的协同构建器被弃用?为什么这样做更好:

fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
    for (x in 1..5) send(x * x)
}
Run Code Online (Sandbox Code Playgroud)

代替

fun produceSquares(): ReceiveChannel<Int> = produce { //no longer an extension function
    for (x in 1..5) send(x * x)
}
Run Code Online (Sandbox Code Playgroud)

kotlin kotlinx.coroutines

10
推荐指数
2
解决办法
658
查看次数

Android服务中的Kotlin协程

我有一个android服务,可在服务器在线时启动并与服务器同步不同类型的数据。我是Kotlin协程的新手,我正在尝试完成以下任务:

fun syncData{
//Job1 make retrofit call to server
//Job2 make retrofit call to server after job1 is done.
//Job3 make retrofit call to server after job 2 is done and so on. 
//After all jobs are done I'll stop service.
}
Run Code Online (Sandbox Code Playgroud)

我在关注这篇文章: Kotlin Coroutines在Android中的正确方法

这给我带来了这个解决方案:

fun syncData() = async(CommonPool){
    try{

        val sync1 = async(CommonPool){
            job1.sync()
        }

        val sync2 = async(CommonPool){
            job2.sync()
        }


        val sync3 = async(CommonPool){
            job3.sync()
        }

        val sync4 = async(CommonPool){
            job4.sync()
        }
        job1.await()
        job2.await()
        job3.await()
        job4.await()
    }catch …
Run Code Online (Sandbox Code Playgroud)

android-service async-await kotlin kotlinx.coroutines

9
推荐指数
2
解决办法
1735
查看次数

如何在使用当前父级Scope的“悬浮乐趣”中启动Kotlin协程?

如何从暂停功能启动协程并使其使用当前的示波器?(这样,直到启动的协程也结束,作用域才结束)

我想写类似下面的内容–

import kotlinx.coroutines.*

fun main() = runBlocking { // this: CoroutineScope
    go()
}

suspend fun go() {
    launch {
        println("go!")
    }
}
Run Code Online (Sandbox Code Playgroud)

但这有一个语法错误:“未解决的参考:启动”。似乎launch必须以下列方式之一运行-

GlobalScope.launch {
    println("Go!")
}
Run Code Online (Sandbox Code Playgroud)

要么

runBlocking {
    launch {
        println("Go!")
    }
}
Run Code Online (Sandbox Code Playgroud)

要么

withContext(Dispatchers.Default) {
    launch {
        println("Go!")
    }
}
Run Code Online (Sandbox Code Playgroud)

要么

coroutineScope {
    launch {
        println("Go!")
    }
}
Run Code Online (Sandbox Code Playgroud)

这些替代方法都不能满足我的需求。代码要么“阻塞”而不是“产生”,要么产生,但是父作用域在父作用域本身结束之前不会等待其完成。

我需要它在当前的父协程作用域中“生成”(启动),并且该父作用域应等待所生成的协程完成,然后结束自身。

我希望a launch内的简单内容suspend fun有效并使用其父范围。

我正在使用Kotlin 1.3cotlinx-coroutines-core:1.0.1

kotlin kotlinx.coroutines

9
推荐指数
2
解决办法
1181
查看次数

带有Kotlin-coroutines的房间观察数据库的变化

因此,我最近开始使用协同程序进行实验,我从Rxjava2切换到协同程序,我还没有掌握它但仍然,我遇到了一个需要观察我的数据库更改并更新对应的UI的情况.

RxJava曾经为我提供Flowables,Completeable等,使用它我可以观察到Db的变化.

    abstract fun insert(data: SomeData): Long

    @Query("SELECT * FROM somedata_table")
    abstract fun getData(): Flowable<List<SomeData>>
Run Code Online (Sandbox Code Playgroud)

所以现在这里我曾经订阅了getData并且总是习惯于观察变化

现在输入coroutines,我使用带有延迟结果的暂停函数来返回我的响应

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    abstract fun insert(data: SomeData): Long

    @Query("SELECT * FROM somedata_table")
    abstract fun getData(): List<SomeData>
Run Code Online (Sandbox Code Playgroud)
suspend fun getAllSomeData():Deferred<List<SomeData>>{
        return GlobalScope.async (context= coroutineContext){
            database.myDao().getData()
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在我无法听取更新,协程中的频道可能是正确的答案吗?但我不确定如何使用Room.

android kotlin kotlinx.coroutines

9
推荐指数
2
解决办法
2525
查看次数

如何限制kotlin协同程序的最大并发性

我有一个Sequence(来自File.walkTopDown),我需要在每个上运行一个长时间运行的操作.我想使用Kotlin最佳实践/协同程序,但我要么没有并行性,要么太多并行性并且遇到"太多打开文件"IO错误.

File("/Users/me/Pictures/").walkTopDown()
    .onFail { file, ex -> println("ERROR: $file caused $ex") }
    .filter { ... only big images... }
    .map { file ->
        async { // I *think* I want async and not "launch"...
            ImageProcessor.fromFile(file)
        }
    }
Run Code Online (Sandbox Code Playgroud)

这似乎没有并行运行,我的多核CPU永远不会超过1 CPU的价值.是否有协同程序运行"NumberOfCores并行操作"值得延期的工作?

使用Kotlin协同程序查看多线程,它首先创建所有作业,然后加入它们,但这意味着在重处理连接步骤之前完成序列/文件树步骤,这似乎......如果!将其拆分为收集和处理步骤意味着收集可以在处理之前运行.

val jobs = ... the Sequence above...
    .toSet()
println("Found ${jobs.size}")
jobs.forEach { it.await() }
Run Code Online (Sandbox Code Playgroud)

parallel-processing multithreading kotlin kotlinx.coroutines

8
推荐指数
4
解决办法
1832
查看次数

如何将Android任务转换为Kotlin Deferred?

Firebase匿名登录返回任务(基本上是Google承诺实施):

val task:Task<AuthResult> = FirebaseAuth.getInstance().signInAnonymously()
Run Code Online (Sandbox Code Playgroud)

如何创建一个signInAnonymous包装器:

  • 这是一个suspend功能,等待task完成

    • suspend fun signInAnonymous(): Unit
  • 它返回一个Deferred对象,异步传递结果

    • fun signInAnonymous() : Deferred

android kotlin firebase kotlinx.coroutines

8
推荐指数
3
解决办法
1290
查看次数

例外情况"缺少主调度员的模块." 仅在发布APK

kotlinx-coroutines-android:1.0.0-RC1在我的Android项目中使用Kotlin 1.3 EAP .我的开发构建成功,应用程序运行正常.但是,当我Generate Signed APK,应用程序仍然构建和运行,但随后崩溃

java.lang.IllegalStateException:Main缺少调度程序的模块.添加提供Main调度程序的依赖项,例如'kotlinx-coroutines-android'

由于dev构建运行良好,显然gradle文件中没有遗漏.我有这些设置:

项目build.gradle:

buildscript {
    ext.kotlin_version = '1.3.0-rc-190'
    ....
Run Code Online (Sandbox Code Playgroud)

模块build.gradle:

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0-RC1'
Run Code Online (Sandbox Code Playgroud)

随着时间的推移,相同的应用程序已经与许多不同版本的实验协同程序一起运行,这是我第一次遇到这个问题.我怀疑EAP工件中有一些临时问题.

我有什么办法让这项工作成功?

android kotlin kotlinx.coroutines

8
推荐指数
1
解决办法
2190
查看次数

如何在 Java 代码中使用 Kotlin 协程实现 NIO Socket(客户端)?

我想使用 Kotlin(v1.3.0)协程和 java.nio.channels。SocketChannel (NIO) 来替代connectAndroid 中的Socket (阻塞 IO)。因为这可以节省很多线程。

下面的代码因为job.await()在 Kotlin 中挂起函数而无法运行,它只能在 Ktolin 协程块中调用。喜欢launch{..}async{..}

// this function will be called by Java Code
fun connect(address: InetSocketAddress, connectTimeout: Int): SocketChannel {

    // Start a new connection
    // Create a non-blocking socket channel
    val socketChannel = SocketChannel.open()
    socketChannel.configureBlocking(false)

    // async calls NIO connect function
    val job = GlobalScope.async(oneThreadCtx) {
        aConnect(socketChannel, address)
    }

    // I what to suspend(NOT block) current Java Thread, until …
Run Code Online (Sandbox Code Playgroud)

android socketchannel kotlin okhttp kotlinx.coroutines

8
推荐指数
2
解决办法
7054
查看次数