Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin流Java互操作回调_Java_Kotlin_Kotlin Coroutines_Kotlin Flow - Fatal编程技术网

Kotlin流Java互操作回调

Kotlin流Java互操作回调,java,kotlin,kotlin-coroutines,kotlin-flow,Java,Kotlin,Kotlin Coroutines,Kotlin Flow,当我想将Kotlin流与普通回调一起使用时,我一直在寻找合适的解决方案或最佳实践。我的用例是,我编写了一个kotlin库,它在内部使用kotlin流,我必须假设用户将使用Java。因此,我认为最好的解决方案是将一个基本回调接口重载到我的flow方法中,并在collect中调用它,如下所示: class KotlinClass { interface Callback { fun onResult(result: Int) } private fun f

当我想将Kotlin流与普通回调一起使用时,我一直在寻找合适的解决方案或最佳实践。我的用例是,我编写了一个kotlin库,它在内部使用kotlin流,我必须假设用户将使用Java。因此,我认为最好的解决方案是将一个基本回调接口重载到我的flow方法中,并在
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")
            }
        });
    } 
}
public class JavaClass {

    public static void main(String[] args) {
        KotlinClass libraryClass = new KotlinClass();
        libraryClass.bar(v -> { System.out.println(v); return Unit.INSTANCE; });
    } 
}
我不确定该怎么办,因为我希望我的Kotlin库能够以一种良好的方式使用Java和Kotlin可用的流


我遇到了
callbackFlow
,但这似乎只是我想让我们把它称为基于回调的API?因为我是Kotlin和Flows的新手,如果我的问题由于缺少Kotlin的一些基本概念而存在缺陷,请道歉。

您不需要在Kotlin代码中创建接口。您可以这样定义条形图:

 fun bar(callback: (Int) -> Unit) {
     runBlocking {
         foo().collect { callback(it) }
     }
 }
从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")
            }
        });
    } 
}
public class JavaClass {

    public static void main(String[] args) {
        KotlinClass libraryClass = new KotlinClass();
        libraryClass.bar(v -> { System.out.println(v); return Unit.INSTANCE; });
    } 
}

您不需要在Kotlin代码中创建接口。您可以这样定义条形图:

 fun bar(callback: (Int) -> Unit) {
     runBlocking {
         foo().collect { callback(it) }
     }
 }
从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")
            }
        });
    } 
}
public class JavaClass {

    public static void main(String[] args) {
        KotlinClass libraryClass = new KotlinClass();
        libraryClass.bar(v -> { System.out.println(v); return Unit.INSTANCE; });
    } 
}

我会给Java客户机更多的流量控制权。我将向回调接口添加一个
onStart
onCompletion
方法。除此之外,我还将使用自己的
CoroutineScope
——可能可以从Java客户端自定义。我不会在Kotlin函数中阻止调用线程-no
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();
        }
    }
}

我会给Java客户机更多的流量控制权。我将向回调接口添加一个
onStart
onCompletion
方法。除此之外,我还将使用自己的
CoroutineScope
——可能可以从Java客户端自定义。我不会在Kotlin函数中阻止调用线程-no
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();
        }
    }
}

谢谢你的回答,我不完全理解的是
倒计时闩锁
的部分,我真的需要从我的Java库中关闭coroutineScope吗,还是在我的Kotlin库中完成后就可以终止它?你也可以从Kotlin中关闭
coroutineScope
,阻塞调用线程也是如此。但你的问题是,什么是好的API。如果你在你的图书馆里这样做,你是非常固执己见的,客户是如何使用你的。从我的观点来看,最好让客户端决定阻塞线程是否是一个好主意,以及超时的时间长度。问题是,我真的想隐藏kotlin库中的所有线程,java库应该只在主线程上为每个收集到的流结果获取回调感谢您的回答,我不完全理解的是
countdownLatch
的部分,我真的需要从我的Java库中关闭coroutineScope吗?还是在我的Kotlin库中完成时终止它?你也可以从Kotlin中关闭
coroutineScope
,阻塞调用线程也是如此。但你的问题是,什么是好的API。如果你在你的图书馆里这样做,你是非常固执己见的,客户是如何使用你的。从我的观点来看,让客户端决定阻塞线程是否是一个好主意,以及超时的时间长度是否更好。问题是,我真的想在kotlin库中隐藏所有线程,java库应该只在主线程上为每个收集到的流结果获取回调。这是一个有效的建议,但我想使用
returnunit.INSTANCE
在我的java代码中是不好的做法,就像这里描述的:?要在我的java代码中使用
Unit
类,我是否需要添加一些kotlin依赖项,因为我不能直接使用它?本文说“目前,还没有办法定义一个参数类型作为Java和Kotlin中的lambda使用,从而让两种语言都觉得它是惯用的。当前的建议是,尽管返回类型为Unit时Java的体验有所降低,但还是更喜欢函数类型。如果您在Java项目中使用kotlin,它应该已经包含kotlin stdlib作为依赖项,不是吗?如果您的库将专门从Java使用,您也可以尝试最后一个建议“定义命名,这是一个有效的建议,但我认为在我的Java代码中使用
return Unit.INSTANCE
将是一种糟糕的做法,就像这里所描述的:?要在我的Java代码中使用
Unit
类,我是否需要添加一些kotlin依赖项,因为我不能直接使用它?本文说“目前,还没有办法定义一个参数类型作为Java和Kotlin中的lambda使用,从而使它在两种语言中都感觉是惯用的。当前的建议是,尽管返回类型为Unit时Java的体验有所降低,但还是更喜欢函数类型。如果您在Java项目中使用kotlin,它应该已经包含kotlin stdlib作为依赖项,不是吗?如果您的库将专门从Java使用,您也可以尝试最后一个建议“定义命名,Java中的SAM接口”。