Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.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
Android 防止同时执行两个挂起函数的一部分_Android_Kotlin_Flow_Stateflow - Fatal编程技术网

Android 防止同时执行两个挂起函数的一部分

Android 防止同时执行两个挂起函数的一部分,android,kotlin,flow,stateflow,Android,Kotlin,Flow,Stateflow,我在ViewModel中并行启动了两种挂起方法: init { viewModelScope.launch(Dispatchers.Default) { launch { loadTotalCirculation() } launch { loadMarketPrice() } } } private suspend fun loadTotalCirculation() { val totalCirculation = bitcoinCh

我在ViewModel中并行启动了两种挂起方法:

init {
    viewModelScope.launch(Dispatchers.Default) {
        launch { loadTotalCirculation() }
        launch { loadMarketPrice() }
    }
}

private suspend fun loadTotalCirculation() {
    val totalCirculation = bitcoinChartsRepository.getTotalCirculation(5, TimeUnit.HOURS)
    _viewState.value = _viewState.value.copy(totalCirculation = chartViewEntityMapper(totalCirculation))
}

private suspend fun loadMarketPrice() {
    val marketPrice = bitcoinChartsRepository.getMarketPrice(27, TimeUnit.DAYS)
    _viewState.value = _viewState.value.copy(marketPrice = chartViewEntityMapper(marketPrice))
}

但是,我希望防止在这两个方法中同时执行
\u viewState.value=\u viewState.value.copy…
部分。实现这一点的最佳方法是什么?

有几种同步并行协同路由的可能性。可能最简单的方法是创建一个单线程上下文,类似于主线程或使用。注意这个互斥是专门为coutroutines设计的,它不是来自Javastdlib的

单线程上下文:

val context = Executors.newSingleThreadExecutor().asCoroutineDispatcher()

private suspend fun loadTotalCirculation() {
    val totalCirculation = bitcoinChartsRepository.getTotalCirculation(5, TimeUnit.HOURS)
    withContext (context) {
        _viewState.value = _viewState.value.copy(totalCirculation = chartViewEntityMapper(totalCirculation))
    }
}

private suspend fun loadMarketPrice() {
    val marketPrice = bitcoinChartsRepository.getMarketPrice(27, TimeUnit.DAYS)
    withContext (context) {
        _viewState.value = _viewState.value.copy(marketPrice = chartViewEntityMapper(marketPrice))
    }
}
或者,您可以通过:
withContext(Dispatchers.main)
重用主线程,而不是创建自己的线程

互斥:

val mutex = Mutex()

private suspend fun loadTotalCirculation() {
    val totalCirculation = bitcoinChartsRepository.getTotalCirculation(5, TimeUnit.HOURS)
    mutex.withLock {
        _viewState.value = _viewState.value.copy(totalCirculation = chartViewEntityMapper(totalCirculation))
    }
}

private suspend fun loadMarketPrice() {
    val marketPrice = bitcoinChartsRepository.getMarketPrice(27, TimeUnit.DAYS)
    mutex.withLock {
        _viewState.value = _viewState.value.copy(marketPrice = chartViewEntityMapper(marketPrice))
    }
}
使用主线程或互斥体可能是首选,因为如果我们创建自己的线程,我们需要确保在不再需要它时正确地停止/关闭它


您可以从官方文档中阅读本文的更多内容:

有几种同步并行协同路由的可能性。可能最简单的方法是创建一个单线程上下文,类似于主线程或使用。注意这个互斥是专门为coutroutines设计的,它不是来自Javastdlib的

单线程上下文:

val context = Executors.newSingleThreadExecutor().asCoroutineDispatcher()

private suspend fun loadTotalCirculation() {
    val totalCirculation = bitcoinChartsRepository.getTotalCirculation(5, TimeUnit.HOURS)
    withContext (context) {
        _viewState.value = _viewState.value.copy(totalCirculation = chartViewEntityMapper(totalCirculation))
    }
}

private suspend fun loadMarketPrice() {
    val marketPrice = bitcoinChartsRepository.getMarketPrice(27, TimeUnit.DAYS)
    withContext (context) {
        _viewState.value = _viewState.value.copy(marketPrice = chartViewEntityMapper(marketPrice))
    }
}
或者,您可以通过:
withContext(Dispatchers.main)
重用主线程,而不是创建自己的线程

互斥:

val mutex = Mutex()

private suspend fun loadTotalCirculation() {
    val totalCirculation = bitcoinChartsRepository.getTotalCirculation(5, TimeUnit.HOURS)
    mutex.withLock {
        _viewState.value = _viewState.value.copy(totalCirculation = chartViewEntityMapper(totalCirculation))
    }
}

private suspend fun loadMarketPrice() {
    val marketPrice = bitcoinChartsRepository.getMarketPrice(27, TimeUnit.DAYS)
    mutex.withLock {
        _viewState.value = _viewState.value.copy(marketPrice = chartViewEntityMapper(marketPrice))
    }
}
使用主线程或互斥体可能是首选,因为如果我们创建自己的线程,我们需要确保在不再需要它时正确地停止/关闭它


您可以从官方文档中阅读本文的更多内容:

您可以使用,但是当您使用
viewModelScope
时,并发性不应该是一个问题,因为它有
Dispatchers.Main.immediate
的支持,所以这两个值修改都将以任何方式在主UI线程上进行。嗨,Pawel,这是一个伟大的观点!但是,我在默认调度程序上启动协同路由,这样它们就可以并发运行。我现在已经更新了上面的代码。您可以使用,但是当您使用
viewModelScope
时,并发性不应该是一个问题,因为它由
Dispatchers.Main.immediate
支持,所以这两个值修改都将以任何方式发生在主UI线程上。嗨,Pawel,这是一个伟大的观点!但是,我在默认调度程序上启动协同路由,这样它们就可以并发运行。我现在已经更新了上面的代码。谢谢!我现在已经使用了互斥解决方案,但也尝试了您建议的另一种方法,即使用主调度程序上下文。我来看看这两种方法的优缺点。这实际上是一个很好的问题:优缺点是什么。我没有足够的信心完全回答这个问题,但我的想法是:我通常避免使用互斥体,因为它们会产生更复杂、可读性更低的代码。任务队列对我来说更自然,所以:参与者模型、事件循环或单线程执行器——它们都以类似的方式工作。在这种特殊情况下,我会说互斥是一种方式。互斥正是它设计的目的。它不依赖于任何外部机械,也没有任何副作用。其他解决方案需要一些外部支持。谢谢!我现在已经使用了互斥解决方案,但也尝试了您建议的另一种方法,即使用主调度程序上下文。我来看看这两种方法的优缺点。这实际上是一个很好的问题:优缺点是什么。我没有足够的信心完全回答这个问题,但我的想法是:我通常避免使用互斥体,因为它们会产生更复杂、可读性更低的代码。任务队列对我来说更自然,所以:参与者模型、事件循环或单线程执行器——它们都以类似的方式工作。在这种特殊情况下,我会说互斥是一种方式。互斥正是它设计的目的。它不依赖于任何外部机械,也没有任何副作用。其他解决方案需要一些外部支持。