Android 不启动挂起功能的全局标志?
我需要启动方法Android 不启动挂起功能的全局标志?,android,kotlin,kotlin-coroutines,Android,Kotlin,Kotlin Coroutines,我需要启动方法getFuelPrice,前提是之前没有启动。为此,我使用全局标志isStartGetFuelPrice smt是这样的: for (currentPass in 0..10) { // some code here viewModelScope.launch(Dispatchers.Main) { if (!isStartedGetFuelPrice) { currentCheck = getFuelPrice(currentCheck)
getFuelPrice
,前提是之前没有启动。为此,我使用全局标志isStartGetFuelPrice
smt是这样的:
for (currentPass in 0..10) {
// some code here
viewModelScope.launch(Dispatchers.Main) {
if (!isStartedGetFuelPrice) {
currentCheck = getFuelPrice(currentCheck)
}
}
}
在迭代1中,方法getFuelPrice
开始,但在迭代2中不得开始。函数getFuelPrice
只能调用一次
这是:
suspend fun getFuelPrice(currentRecognizedCheck: Check): Check {
isStartedGetFuelPrice = true
// some logic here
isStartedGetFuelPrice = false
return currentRecognizedCheck
但我认为全球旗帜不是一个好的解决方案。还有其他更好的方法吗?对于并发代码,确实不建议使用全局可变共享状态 不过,您可以尝试以下方法:
data class Once(private val block: suspend () -> Unit) {
private val ran = AtomicBoolean(false)
suspend fun run() {
if (ran.compareAndSet(false, true)) {
block()
}
}
}
然后:
您还可以让一次
返回一个值,但为此,您需要使用Kotlin互斥体
:
data class Once<out T : Any>(private val block: suspend () -> T) {
private val mutex = Mutex()
private lateinit var r : T
suspend fun run(): T {
mutex.lock()
if (!this::r.isInitialized) {
r = block()
}
mutex.unlock()
return r
}
}
如果您不喜欢互斥体,还有另一个窍门:
class Once<T>(block: suspend () -> T) {
private val r = GlobalScope.async(start = CoroutineStart.LAZY) {
block()
}
suspend fun run() = r.await()
}
类一次(块:suspend()->T){
private val r=GlobalScope.async(start=CoroutineStart.LAZY){
块()
}
suspend fun run()=r.await()
}
是否要按顺序调用此函数11次,每次都等待结果?代码中是否还有其他地方可以调用getFuelPrice()
,并且还需要这些调用来等待轮到它们?如果是这样,那么另一个函数应该等待它准备好还是放弃呢?@Tenfour04只在这里调用getFuelPrice()。我只想调用一次函数getFuelPrice()。那么什么是for(currentPass in 0..10)
for?@Tenfour04循环需要其他东西。我不明白。如果你只想调用它一次,为什么不把它移出循环呢?或者如果(currentPass==0){}将其包装在中?假设getFuelPrice
必须是一个挂起函数,您还需要将block
和run()
标记为suspend
@AlexeySohin getFuelPrice必须返回我的自定义对象检查
suspend fun run(): T {
return mutex.withLock {
if (!this::r.isInitialized) {
r = block()
}
r
}
}
class Once<T>(block: suspend () -> T) {
private val r = GlobalScope.async(start = CoroutineStart.LAZY) {
block()
}
suspend fun run() = r.await()
}