长时间网络操作后使用主线程 [英] Use main thread after long network operation
问题描述
在我的android应用中,我的网络操作时间很长.操作完成后,我需要更新用户界面.
In my android app I has long network operation. After operation is finished I need to update my ui.
因此,需要在后台线程中执行较长的操作.
So as result long operation need to execute in background thread.
摘要:
private val isShowProgressLiveData = MutableLiveData<Boolean>()
// launch a new coroutine in background and continue
GlobalScope.launch() {
try {
val executeOperations = OperationFactory.createExecuteTraderOperation(Trader.Operation.CREATE, base, quote)
val response: Response<Void> = executeOperations.await()
if (response.isSuccessful) {
isShowProgressLiveData.value = false
isForwardToTradersLiveData.value = true
} else {
Debug.w(TAG, "doClickStart_error")
}
} catch (e: Throwable) {
Debug.e(TAG, "doClickStart_network error: $e.message", e)
}
}
但我在
isShowProgressLiveData.value = false
错误消息:
java.lang.IllegalStateException: Cannot invoke setValue on a background thread
at androidx.lifecycle.LiveData.assertMainThread(LiveData.java:461)
at androidx.lifecycle.LiveData.setValue(LiveData.java:304)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
at com.myoperation.AddTraderViewModel$doClickStart$3.invokeSuspend(AddTraderViewModel.kt:55)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:238)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
我需要在主线程中更新ui.那我该如何解决呢?
I need to update my ui in main thread. So how I can fix this?
推荐答案
您可以像withContext(Dispatchers.Main)
一样切换到主线程
当您用启动程序启动协程时,将在Dispatchers.Default
上启动.最好是这样指定它:
You can switch to main thread like with the withContext(Dispatchers.Main)
When you fire a coroutine with launch will start on the Dispatchers.Default
. The best is to specify it like this:
GlobalScope.launch(Dispatchers.IO) {
try {
val executeOperations = OperationFactory.createExecuteTraderOperation(Trader.Operation.CREATE, base, quote)
val response: Response<Void> = executeOperations.await()
if (response.isSuccessful) {
withContext(Dispatchers.Main){ //switched to Main thread
isShowProgressLiveData.value = false
isForwardToTradersLiveData.value = true
}
} else {
Debug.w(TAG, "doClickStart_error")
}
} catch (e: Throwable) {
Debug.e(TAG, "doClickStart_network error: $e.message", e)
}
}
或者您可以只使用.postValue()
而不是.value
或.setValue()
并忘记withContext()
.
Or you can just use .postValue()
instead of .value
or .setValue()
and forget about withContext()
.
这篇关于长时间网络操作后使用主线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!