代码之家  ›  专栏  ›  技术社区  ›  Aliaksei

科特林暂停娱乐

  •  6
  • Aliaksei  · 技术社区  · 7 年前

    我有Kotlin接口

    interface FileSystem {
        suspend fun getName(path: Path): List<String>
    }
    

    Continuation <? super List<String>>
    

    enter image description here

    1 回复  |  直到 6 年前
        1
  •  7
  •   Marko Topolnik    6 年前

    Kotlin使用基于堆栈的常规调用约定和 连续传球风格 CPS变换 总的来说 suspend fun s通过添加一个隐式参数,可以使用该对象从调用函数的位置继续程序。这就是Kotlin如何成功地实现在函数体中暂停执行的技巧:它提取continuation对象,将其保存在某个地方,然后使函数返回(还没有生成其值)。稍后,它可以通过调用continuation对象来实现跳入函数体中间的效果。

    continuation基本上是一个回调对象,就像那些熟悉的异步javaapi一样。suspendable函数不返回其结果,而是将其结果传递给continuation。打电话给 在java中,您必须创建这样一个回调。下面是一个例子:

    Continuation<List<String>> myCont = new Continuation<List<String>>() {
        @Override public void resume(List<String> result) {
            System.out.println("Result of getName is " + result);
        }
        @Override public void resumeWithException(Throwable throwable) {
            throwable.printStackTrace();
        }
        @NotNull @Override public CoroutineContext getContext() {
            return Unconfined.INSTANCE;
        }
    };
    

    resumeWith(result: Result<T>) 哪里 Result 是结果类型和 internal class Failure

    我们还要创建 FileSystem 接口:

    class MockFs : FileSystem {
        override suspend fun getName(path: Path): List<String> {
            suspendCoroutine<Unit> {
                println("getName suspended")
            }
            println("getName resumed")
            return listOf("usr", "opt")
        }
    }
    

    现在我们准备从Java调用它:

    Object result = new MockFs().getName(Paths.get(""), myCont);
    System.out.println("getName returned " + result);
    

    getName suspended
    getName returned
    kotlin.coroutines.experimental.intrinsics.CoroutineSuspendedMarker@6ce253f1
    

    getName() 返回一个特殊的标记对象,该对象表示函数被挂起。函数将在恢复后将其实际结果传递给回调。

    MockFs 所以我们可以进入下一页:

    class MockFs : FileSystem {
        var continuation : Continuation<Unit>? = null
    
        override suspend fun getName(path: Path): List<String> {
            suspendCoroutine<Unit> {
                continuation = it
                println("getName suspended")
            }
            println("getName resumed")
            return listOf("usr", "opt")
        }
    }
    

    MockFs mockFs = new MockFs();
    mockFs.getName(Paths.get(""), myCont);
    mockFs.getContinuation().resume(Unit.INSTANCE);
    

    这将打印

    getName suspended
    getName resumed
    Result of getName is [usr, opt]
    

    一个 也可以直接返回结果。例如,用这个 模型

    class MockFs : FileSystem {
        override suspend fun getName(path: Path) = listOf("usr", "opt") 
    }
    

    在Java中我们可以说

    System.out.println(new MockFs().getName(Paths.get(""), myCont));
    

    [usr, opt] . 我们甚至可以通过一个空的 Continuation .

    Object retVal = mockFs.getName(Paths.get(""), myCont);
    if (retVal != IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
        myCont.resume((List<String>) retVal);
    }
    

    否则,必须复制处理函数结果的代码。