我有一个具体例子的一般性问题:在拍照时,我想在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) 更新协程 1.3.0-RC
工作版本:
@FlowPreview
suspend fun streamTest(): Flow<String> = channelFlow {
listener.onSomeResult { result ->
if (!isClosedForSend) {
offer(result)
}
}
awaitClose {
listener.unsubscribe()
}
}
Run Code Online (Sandbox Code Playgroud)
另请查看 Roman Elizarov 的这篇 Medium 文章:回调和 Kotlin 流程
原始问题
我有一个流发出多个字符串:
@FlowPreview
suspend fun streamTest(): Flow<String> = flowViaChannel { channel ->
listener.onSomeResult { result ->
if (!channel.isClosedForSend) {
channel.sendBlocking(result)
}
}
}
Run Code Online (Sandbox Code Playgroud)
一段时间后,我想取消订阅流。目前我执行以下操作:
viewModelScope.launch {
beaconService.streamTest().collect {
Timber.i("stream value $it")
if(it == "someString")
// Here the coroutine gets canceled, but streamTest is still executed …Run Code Online (Sandbox Code Playgroud) 在使用 Kotlin 进行编码时,是选择其中一种更好还是另一种更好?
该视频:Java 21 新功能:虚拟线程 #RoadTo21似乎不赞成将虚拟线程用于非 IO 或非阻塞任务。
我什至在 Kotlin 代码中为 CPU 密集型任务创建了左右协程。这已经不行了吗?
使用channel.close()关闭kotlinx.coroutines通道的原因是什么以及不手动关闭通道的负面影响是什么?如果我不手动关闭频道会有一些不必要的处理?是否会在某个地方引用阻止其成为GCd的频道?或者,关闭功能是否仅作为向渠道的潜在用户通知其不再可以使用的方式存在.
(转自Kotlin论坛的问题https://discuss.kotlinlang.org/t/closing-coroutine-channels/2549)
我是一名从 Java 切换到 Kotlin 的 Android 开发人员,我计划使用协程来处理异步代码,因为它看起来非常有前途。
回到 Java,为了处理异步代码,我使用Executor该类在另一个线程中执行一段耗时的代码,远离 UI 线程。我AppExecutors在我的xxxRepository课程中注入了一个课程来管理一组Executor. 它看起来像这样:
public class AppExecutors
{
private static class DiskIOThreadExecutor implements Executor
{
private final Executor mDiskIO;
public DiskIOThreadExecutor()
{
mDiskIO = Executors.newSingleThreadExecutor();
}
@Override
public void execute(@NonNull Runnable command)
{
mDiskIO.execute(command);
}
}
private static class MainThreadExecutor implements Executor
{
private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command)
{
mainThreadHandler.post(command);
}
}
private static volatile AppExecutors INSTANCE; …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一个对象,它可以在自己的线程中顺序执行一些任务,就像它是一个队列一样。
以下示例仅用于演示我的设置,可能完全错误。
class CoroutinesTest {
fun a() {
GlobalScope.launch {
println("a started")
delay(1000)
println("a completed")
}
}
fun b() {
GlobalScope.launch {
println("b started")
delay(2000)
println("b completed")
}
}
fun complex() {
a()
b()
}
}
fun main() {
runBlocking {
val coroutinesTest = CoroutinesTest()
coroutinesTest.complex()
delay(10000)
}
}
Run Code Online (Sandbox Code Playgroud)
现在这段代码打印以下内容
a started
b started
a completed
b completed
Run Code Online (Sandbox Code Playgroud)
这意味着a和b并行执行。方法a,b和complex可以从不同的线程调用。当然,该complex方法也应该支持这个概念。现在,我需要一种机制,允许我一次只执行一个任务,这样我就可以获得以下输出:
a started
a completed
b started
b completed
Run Code Online (Sandbox Code Playgroud)
我做了一些研究,认为 …
当从活动、片段或 Android 架构组件 ViewModel 启动协程时,使用绑定到该视图组件生命周期的协程范围是完全有意义的,以避免泄漏和释放资源,例如在用户离开时取消网络请求屏幕。
但在其他情况下,即使用户离开屏幕,您也不想取消协程,例如执行网络请求进行分析或写入数据库时。GlobalScope在这种情况下启动协程可以吗?启动这些协程的对象大多是Singletons,所以它们无论如何都会在应用程序的生命周期内存活,所以没有泄漏的危险,对吧?
在 GlobalScope 上,Kotlin 文档非常清楚:
应用程序代码通常应该使用应用程序定义的 CoroutineScope。强烈建议不要在 GlobalScope 实例上使用 async 或 launch。
在这些情况下可以使用 GlobalScope 吗?如果不是,我的应用程序定义的 CoroutineScope 应该是什么样的?
我正在使用下面的脚本创建一个协程:
fun bar(completion: () -> Unit) {
GlobalScope.launch(Dispatchers.IO) {
val lambda = {
withContext(Dispatchers.Main) { //Suspension functions can be called only within coroutine body
completion()
}
}
foo(lambda)
}
}
fun foo(lambda: () -> Unit) {
//...do something heavy
lambda()
}
Run Code Online (Sandbox Code Playgroud)
但是Suspension functions can be called only within coroutine body当我调用时出现错误,withContext(Dispatchers.Main)因为 lambda 更改了上下文。我无法更改foo(lambda: () -> Unit)为,foo(lambda: suspend () -> Unit)因为它来自外部库。
知道我可以withContext(Dispatchers.Main)在launch上下文中创建的 lambda 内部调用什么吗?
谢谢!
我\xc2\xb4m试图找出在函数成员上测试这种类型的最简单方法,我\xc2\xb4见过更复杂的情况,例如协程 - 单元测试 viewModelScope.launch 方法,但没有\xc2\xb4t解决
\n\n\nListScreenViewModel.kt
\n
@HiltViewModel\nclass ListScreenViewModel @Inject constructor(): ViewModel() {\n\n private var _itemsNumber = mutableStateOf(0)\n\n private var _testList = mutableStateOf(listOf<String>())\n val testList = _testList\n\n fun addItem() {\n viewModelScope.launch {\n _itemsNumber.value++\n _testList.value += (\n "Item ${_itemsNumber.value}"\n )\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\nListScreenViewModelTest.kt
\n
class ListScreenViewModelTest{\n\n private lateinit var viewModel: ListScreenViewModel\n\n @Before\n fun setup(){\n viewModel = ListScreenViewModel()\n }\n\n @Test\n fun `add an item to the list of items`(){\n val numberOfItems = viewModel.testList.value.size\n viewModel.addItem()\n …Run Code Online (Sandbox Code Playgroud)