android - CoroutineExceptionHandler 不适用于 ViewModelScope 和 Koin
问题描述
我有一种使用协程获取设备并用于viewModelScope.launch
运行协程的方法。我想使用 捕获错误CoroutineExceptionHandler
,但出现错误:
E/[Koin]: Instance creation error : could not create instance for [Factory:'com.test.presentation.viewModel.ActivateDeviceViewModel']: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter context
kotlin.coroutines.CombinedContext.plus(Unknown Source:2)
kotlinx.coroutines.CoroutineContextKt.newCoroutineContext(CoroutineContext.kt:33)
kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:52)
kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
com.test.presentation.viewModel.ActivateDeviceViewModel.fetchDevices(ActivateDeviceViewModel.kt:42)
com.test.presentation.viewModel.ActivateDeviceViewModel.<init>(ActivateDeviceViewModel.kt:29)
com.test.di.ModulesKt$viewModelModule$1$2.invoke(Modules.kt:63)
com.test.di.ModulesKt$viewModelModule$1$2.invoke(Modules.kt:63)
org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:51)
org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:36)
org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:103)
org.koin.core.scope.Scope.resolveInstance(Scope.kt:236)
org.koin.core.scope.Scope.access$resolveInstance(Scope.kt:34)
org.koin.core.scope.Scope$get$1.invoke(Scope.kt:199)
org.koin.core.time.MeasureKt.measureDurationForResult(Measure.kt:75)
org.koin.core.scope.Scope.get(Scope.kt:198)
com.test.presentation.fragment.ActivateDeviceFragment$special$$inlined$inject$default$1.invoke(ComponentCallbackExt.kt:69)
kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
com.test.presentation.fragment.ActivateDeviceFragment.getViewModel(ActivateDeviceFragment.kt:39)
com.test.presentation.fragment.ActivateDeviceFragment.access$getViewModel(ActivateDeviceFragment.kt:37)
com.test.presentation.fragment.ActivateDeviceFragment$handleActivateDeviceResult$1$1.invokeSuspend(ActivateDeviceFragment.kt:51)
kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
androidx.lifecycle.DispatchQueue.drainQueue(DispatchQueue.kt:75)
androidx.lifecycle.DispatchQueue.resume(DispatchQueue.kt:54)
androidx.lifecycle.LifecycleController$observer$1.onStateChanged(LifecycleController.kt:40)
androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:354)
androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:265)
androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:307)
androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:148)
androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:134)
androidx.fragment.app.Fragment.performStart(Fragment.java:3024)
androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:568)
androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:277)
androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1327)
androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2757)
androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2707)
androidx.fragment.app.Fragment.performStart(Fragment.java:3028)
androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:568)
androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:277)
androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1327)
androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2757)
androidx.fragm.
请告诉我我做错了什么以及如何解决?谢谢
分段
class ActivateDeviceFragment : Fragment(R.layout.fragment_activate_device) {
private val viewModel: ActivateDeviceViewModel by inject()
// ....
}
查看模型
class ActivateDeviceViewModel constructor(
private val activateDeviceUseCase: ActivateDeviceUseCase,
) : ViewModel() {
init {
fetchDevices()
}
private val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
Timber.tag("test").d(throwable)
}
private fun fetchDevices() {
viewModelScope.launch(exceptionHandler) {
}
}
}
koin 模块
val useCaseModule = module {
single { ActivateDeviceUseCase() }
}
val viewModelModule = module {
viewModel { ActivateDeviceViewModel(get() }
}
解决方案
它与 Koin 无关。
日志显示exceptionHandler
inviewModelScope.launch(exceptionHandler)
实际上为 null,并且抛出NullPointerException
.
这是因为您触发了fetchDevices()
内部init{}
,其中的实例化exceptionHandler
尚未准备好(意味着它为空)。
因此,您不应该调用fetchDevices()
inside init{}
。例如,您可以onViewCreated(){ viewModel.fetchDevices }
改为在 Fragment 中调用它。没事的。
推荐阅读
- c - 这个 scanf { scanf("%[^\n]%*c", s);} in c 的含义
- dart - 覆盖子类中的 hashCode 和 operator==
- java - Java中的字符串数组排序列表
- java-8 - 我可以从数字列表中创建一个包含多个 put 的地图列表吗?
- jquery - 如何获取搜索内容的默认页码?
- unity3d - Unity 编辑器脚本调试堆栈跟踪错误
- node.js - 多商品订单的 MongoDB 模型设计
- c# - 添加外部类
- amazon-web-services - 将 Kibana 导出为 CSV
- javascript - Webpack DevServer 太慢还是我做错了什么?