android - 如何解决致命异常:DefaultDispatcher-worker-4
问题描述
我已经编写了一个新用例来与使用 Flow 的 api 进行通信,我猜我没有在主线程和 IO 线程之间的用例中正确处理线程,
这是我得到的错误
-01-18 02:20:40.555 26602-26870/com.xxx.xx.staging E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-4
Process: com.xxx.xx.staging, PID: 26602
java.lang.IllegalStateException: Event bus [Bus "fill_order"] accessed from non-main thread null
at com.squareup.otto.ThreadEnforcer$2.enforce(ThreadEnforcer.java:47)
at com.squareup.otto.Bus.post(Bus.java:317)
at com.xxx.xx.fragments.filller.fillorder.BasefillOrderFragment.postFldeckStatusUpdateEvent(BasefillOrderFragment.java:117)
at com.xxx.xx.fragments.filller.fillorder.fillOrderDataFragment.postFldeckStatusUpdateEvent(fillOrderDataFragment.java:1955)
at com.xxx.xx.fragments.filller.fillorder.fillOrderDataFragment.updateView(fillOrderDataFragment.java:845)
at com.xx.xx.fragments.filller.fillorder.fillOrderDataFragment.legacyUpdateView(fillOrderDataFragment.java:2317)
at com.xxx.xx.clean.fillorder.presenter.BasefillDataPresenter.onStartfilllingSuccess(BasefillDataPresenter.kt:460)
at com.xxx.xx.clean.fillorder.presenter.BasefillDataPresenter.handleStartfilllingClicked(BasefillDataPresenter.kt:315)
at com.xxx.xx.clean.fillorder.presenter.BasefillDataPresenter.access$handleStartfilllingClicked(BasefillDataPresenter.kt:49)
错误出现在 .handleStartfilllingClicked(view, it) 中。搜集
我正在调用 startfilllingUseCaseFlow 用例,这可能是问题所在
@FlowPreview
fun initFlowSubscription(view: View) {
launch {
view.startfilllingObservableFlow
.conflate()
.catch {
onStartfilllingError(view)
}
.flatMapMerge {
if (!hasOpenInopIncidents()) {
equipmentProvider.get()?.let {
startfilllingUseCaseFlow(StartfilllingUseCaseFlow.Params(it))
}!!
} else {
val incidentOpenResponse = GenericResponse(false)
incidentOpenResponse.error = OPEN_INCIDENTS
flowOf(incidentOpenResponse)
}
}
.collect {
handleStartfilllingClicked(view, it) // ERROR IS HERE
}
}
}
private fun handleStartfilllingClicked(view: View, response: GenericResponse) {
if (response.success == false && response.error == OPEN_INCIDENTS) {
view.showCannotProceedInopIncidentDialog()
view.hideLoader(false)
return
}
onStartfilllingSuccess(view) // Error is here
}
开始填充用例流
class StartfilllingUseCaseFlow @Inject constructor(
private val currentOrderStorage: CurrentOrderStorage,
private val fillOrderRepository: fillOrderRepository,
private val app: App
): FlowUseCase<StartfilllingUseCaseFlow.Params, GenericResponse>() {
override suspend fun run(params: Params): Flow<GenericResponse> {
val startTime = DateTime()
val action = TimestampedAction(
app.session.user.id, null, startTime
)
return flowOf(fillOrderRepository.startfilllingSuspend(
currentOrderStorage.fillOrder!!.id,
action
)).onEach { onSuccess(startTime, params.equipment) }
.catch { e -> e.message?.let { onError(it) } }
.flowOn(Dispatchers.IO)
}
private fun onSuccess(startTime: DateTime, equipment: Equipment) {
if (currentOrderStorage.getfillOrder() == null) return
currentOrderStorage.getfillOrder()!!.setStatus(fillOrderData.STATUS_fillLING)
equipment.times.start = startTime
app.saveState()
}
private fun onError(errorMessage: String) {
Timber.e(errorMessage, "Error calling started fillling! %s", errorMessage)
}
data class Params(val equipment: Equipment)
}
我猜我在这里没有正确处理 IO 和主线程
abstract class FlowUseCase<in Params, out T>() {
abstract suspend fun run(params: Params): Flow<T>
suspend operator fun invoke(params: Params): Flow<T> = run(params).flowOn(Dispatchers.IO)
}
你能建议我在哪里弄错了吗
谢谢R
解决方案
您正在尝试更新 Coroutines 默认线程中的视图。所有视图更新都必须在 MainThread 中。尝试:
fun initFlowSubscription(view: View) {
launch(Dispatchers.Main) {
//enter code here
}
}
这可能会产生另一个错误,因为您在主线程中执行了太多进程。为了避免你。可以使用“异步”并在之后更新您的视图:
示例:
fun initFlowSubscription(view: View) {
launch(Dispatchers.Main) {
val asyncValue = async(Dispatchers.IO) {
//Do yours suspend fun
}
val value = asyncValue.await()
}
}
这个例子应该你没问题,避免停止用户 UI
推荐阅读
- html - 在新选项卡中显示 PDF
- ssl - 处理 local_name 中的多个域
- java - 在 android studio 中的活动之间传递数据
- php - 如何在 Laravel 中实现存储库模式
- javascript - 使用表格导航滚动不起作用
- javascript - 多个过滤器在显示一些折旧问题的 AWS 服务器中不起作用,但在 localhost 中运行良好。如何解决这个问题?
- c# - 如何使用 C# 从共享文件夹中获取权限?
- java - 如何在移动应用程序屏幕上显示数据?
- python - 如何仅提取时代细节并在熊猫数据框中保留其他内容?
- python - 如何在 Python websocket 中查看关闭连接的状态码?