java - Kotlin Flows Java 互操作回调
问题描述
当我想将 Kotlin Flows 与普通回调一起使用时,我一直在寻找合适的解决方案或最佳实践。我的用例是我编写了一个在内部使用 Kotlin Flow 的 kotlin 库,并且我必须假设用户将使用 Java。所以我认为最好的解决方案是将基本回调接口重载到我的流方法并以collect
如下方式调用它:
class KotlinClass {
interface Callback {
fun onResult(result: Int)
}
private fun foo() = flow {
for (i in 1..3) {
emit(i)
}
}
fun bar(callback: Callback) {
runBlocking {
foo().collect { callback.onResult(it) }
}
}
private fun main() {
bar(object : Callback {
override fun onResult(result: Int) {
TODO("Not yet implemented")
}
})
}
在我的 Java 应用程序中,我可以像这样简单地使用它:
public class JavaClass {
public void main() {
KotlinClass libraryClass = new KotlinClass();
libraryClass.bar(new KotlinClass.Callback() {
@Override
public void onResult(int result) {
// TODO("Not yet implemented")
}
});
}
}
我不确定要走的路是什么,因为我想让我的 Kotlin 库使用 Flows 以良好的方式用于 Java 和 Kotlin。
我遇到过,callbackFlow
但这似乎只有当我想称之为 flow-ify 一个基于回调的 API 时?因为我对 Kotlin 和 Flows 很陌生,如果我的问题因缺少 kotlin 的一些基本概念而存在缺陷,请道歉。
解决方案
我会给 Java 客户端更多的流控制权。我会在你的回调接口中添加一个onStart
andonCompletion
方法。除此之外,我会使用自己的CoroutineScope
——也许可以从 Java 客户端定制。而且我不会阻止 Kotlin 函数中的调用线程 - 不runBlocking
。
@InternalCoroutinesApi
class KotlinClass {
val coroutineScope = CoroutineScope(Dispatchers.Default)
interface FlowCallback {
@JvmDefault
fun onStart() = Unit
@JvmDefault
fun onCompletion(thr: Throwable?) = Unit
fun onResult(result: Int)
}
private fun foo() = flow {
for (i in 1..3) {
emit(i)
}
}
fun bar(flowCallback: FlowCallback) {
coroutineScope.launch {
foo().onStart { flowCallback.onStart() }
.onCompletion { flowCallback.onCompletion(it) }
.collect { flowCallback.onResult(it) }
}
}
fun close() {
coroutineScope.cancel()
}
}
现在,Java 客户端可以完全控制如何启动、收集和取消流程。例如,您可以使用闩锁等待完成、设置超时并取消协同程序范围。这首先看起来像很多代码,但通常您需要这种灵活性。
public class JavaClass {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
KotlinClass libraryClass = new KotlinClass();
libraryClass.bar(new KotlinClass.FlowCallback() {
@Override
public void onCompletion(@Nullable Throwable thr) {
latch.countDown();
}
@Override
public void onResult(int result) {
System.out.println(result);
}
});
try {
latch.await(5, TimeUnit.SECONDS);
} finally {
libraryClass.close();
}
}
}
推荐阅读
- lstm - 使用 LSTM 进行二进制时间序列预测
- ruby-on-rails - API 调用期间的 AbstractController::DoubleRenderError
- node.js - Nestjs没有返回空的json对象
- python-3.x - 如何将元音替换为另一个值?(a 到 e,e 到 i 等)
- python-3.x - Splunk Python SDK API job.results 限制为 50k 结果。试图设置一个偏移量来提取多个 50k 的块,但不知道如何让它工作
- c# - 如何包装 Func
C# 中参数的数量和类型未知? - javascript - 使用 toLocaleString 格式化小数以显示 2 个小数和一个逗号
- angular - 如何在 ngFor 循环表单元素中使用输入法
- flutter - Flutter Promise with modal Loading Animation while async task
- java - Java - 从 HashMap 单键多值中获取键(反向映射)