Kotlin Multiplatform:IllegalStateException:必须是主线程
Kotlin Multiplatform: IllegalStateException: Must be main thread
我正在使用 Koin 3.0.0-alpha-4
版本,当我尝试使用 koin
注入的 class 时,它会为 iOS 端抛出异常:
KotlinException=kotlin.IllegalStateException: Must be main thread, KotlinExceptionOrigin
我有一个单身人士 class ,我正在使用 koin 初始化对象:
@ThreadLocal
object ObjectFactory : KoinComponent{
val appStateRepository: AppStateRepository by inject()
val appStateRepositoryDemo = AppStateRepository()
}
如果我在由 koin 注入的后台线程 (Dispatchers.Default
) 中使用 appStateRepository
,那么它会抛出异常 IllegalStateException: Must be main thread
,但是如果我使用 appStateRepositoryDemo 则它工作正常
这是我从 iOS 调用的注入模块的方法
fun initKoinIos(
userDefaults: NSUserDefaults,
doOnStartup: () -> Unit
): KoinApplication = initKoin {
module {
...
single { doOnStartup }
}
}
fun initKoin(appDeclaration: KoinAppDeclaration = {}) = startKoin {
appDeclaration()
modules(
platformModule,
networkModule,
useCaseModules,
repositoryModule,
commonUtils,
)
}
用法如下:
fun testRepoAccess() {
ObjFactory.appStateRepository.test() // Ok, here we are in main thread
CoroutineScope(Dispatchers.Default).launch {
ObjFactory.appStateRepositoryDemo.test() // Ok
ObjFactory.appStateRepository.test() // Not Ok, throws exception (Must be main thread)
}
}
预期行为
它应该适用于 iOS 就像它适用于 Android
Koin 3.0.0-alpha-4
附加模块定义
Coroutines 1.4.2-native-mt
更新
我使用了错误的 Koin 库名称,现在我使用:
io.insert-koin:koin-core:3.0.1
现在我有另一个例外:
kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared org.koin.core.context.GlobalContext.KoinInstanceHolder@1c02ca8 from other thread
Kotlin/Native 上的 Koin 需要在主线程上注入,以避免冻结 Koin 状态。因此,您实际上无法直接从后台线程注入。
添加一个特殊的注入方法,允许您通过切换到主线程来注入,本来打算添加到 Koin 中,但我很确定它永远不会在代码中结束。主要是因为很少有人需要它。
所以,无论如何,您不能用 Koin 做到这一点。您可以尝试 Kodein,但我编写 Koin 的实现恰恰是为了抛出,因为从另一个线程触摸 Koin 会冻结其中的所有内容,而这可能不是您想要做的。
我知道没有人喜欢没有答案,但为什么 ObjectFactory
@ThreadLocal
?我假设让它保持可变,但如果 appStateRepository
是单个的,它无论如何都会被冻结。
我正在使用 Koin 3.0.0-alpha-4
版本,当我尝试使用 koin
注入的 class 时,它会为 iOS 端抛出异常:
KotlinException=kotlin.IllegalStateException: Must be main thread, KotlinExceptionOrigin
我有一个单身人士 class ,我正在使用 koin 初始化对象:
@ThreadLocal
object ObjectFactory : KoinComponent{
val appStateRepository: AppStateRepository by inject()
val appStateRepositoryDemo = AppStateRepository()
}
如果我在由 koin 注入的后台线程 (Dispatchers.Default
) 中使用 appStateRepository
,那么它会抛出异常 IllegalStateException: Must be main thread
,但是如果我使用 appStateRepositoryDemo 则它工作正常
这是我从 iOS 调用的注入模块的方法
fun initKoinIos(
userDefaults: NSUserDefaults,
doOnStartup: () -> Unit
): KoinApplication = initKoin {
module {
...
single { doOnStartup }
}
}
fun initKoin(appDeclaration: KoinAppDeclaration = {}) = startKoin {
appDeclaration()
modules(
platformModule,
networkModule,
useCaseModules,
repositoryModule,
commonUtils,
)
}
用法如下:
fun testRepoAccess() {
ObjFactory.appStateRepository.test() // Ok, here we are in main thread
CoroutineScope(Dispatchers.Default).launch {
ObjFactory.appStateRepositoryDemo.test() // Ok
ObjFactory.appStateRepository.test() // Not Ok, throws exception (Must be main thread)
}
}
预期行为 它应该适用于 iOS 就像它适用于 Android
Koin 3.0.0-alpha-4
附加模块定义
Coroutines 1.4.2-native-mt
更新
我使用了错误的 Koin 库名称,现在我使用:
io.insert-koin:koin-core:3.0.1
现在我有另一个例外:
kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared org.koin.core.context.GlobalContext.KoinInstanceHolder@1c02ca8 from other thread
Kotlin/Native 上的 Koin 需要在主线程上注入,以避免冻结 Koin 状态。因此,您实际上无法直接从后台线程注入。
添加一个特殊的注入方法,允许您通过切换到主线程来注入,本来打算添加到 Koin 中,但我很确定它永远不会在代码中结束。主要是因为很少有人需要它。
所以,无论如何,您不能用 Koin 做到这一点。您可以尝试 Kodein,但我编写 Koin 的实现恰恰是为了抛出,因为从另一个线程触摸 Koin 会冻结其中的所有内容,而这可能不是您想要做的。
我知道没有人喜欢没有答案,但为什么 ObjectFactory
@ThreadLocal
?我假设让它保持可变,但如果 appStateRepository
是单个的,它无论如何都会被冻结。