【问题标题】:Koin Context Isolation: setup correctly and avoid random NoBeanDefFoundExceptionKoin 上下文隔离:正确设置并避免随机 NoBeanDefFoundException
【发布时间】:2021-10-12 15:25:31
【问题描述】:

我有一个我打包和发布的 Android 库模块。这是不同应用程序的依赖项,有些使用 Koin,有些不使用,因此我想使用 Koin 的 context isolation

按照文档,我添加了一个 koin 组件和上下文,如下所示:

internal object LocalKoinContext {
    lateinit var koinApplication: KoinApplication
}

// Custom KoinComponent using the local instance & not the Global context
interface CustomKoinComponent : KoinComponent {
    // override the used Koin instance to use the local koin application instance (LocalKoinContext.koinApplication)
    override fun getKoin(): Koin = LocalKoinContext.koinApplication.koin
}

并像这样添加创建 koinApplication:

// Local Koin application instance
LocalKoinContext.koinApplication = koinApplication {
    // use AndroidLogger as Koin Logger - default Level.INFO
    androidLogger(Level.ERROR)

    // use the Android context given there
    androidContext(applicationContext)

    // load properties from assets/koin.properties file
    androidFileProperties()

    // declare used modules
    modules(theModule)
}

我有一个使用本地 Koin 组件中的视图模型的活动,我曾经在该活动的 onCreate 内实例化 koinApplication:

class FirstActivity : AppCompatActivity(),
    CustomKoinComponent {

    private val sharedViewModel by viewModel<MySharedViewModel>()
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Local Koin application instance
        LocalKoinContext.koinApplication = koinApplication {
             // use AndroidLogger as Koin Logger - default Level.INFO
             androidLogger(Level.ERROR)

             // use the Android context given there
             androidContext(applicationContext)

             // load properties from assets/koin.properties file
             androidFileProperties()

             // declare used modules
             modules(theModule)
         }
     }

问题是我随机得到NoBeanDefFoundException

Caused by org.koin.core.error.NoBeanDefFoundException: No definition found for class:'my.package.name.MySharedViewModel'. Check your definitions!
       at org.koin.core.scope.Scope.throwDefinitionNotFound(Scope.java:264)
       at org.koin.core.scope.Scope.resolveInstance(Scope.java:233)
       at org.koin.core.scope.Scope.get(Scope.java:204)
       at org.koin.androidx.viewmodel.factory.DefaultViewModelFactory.create(DefaultViewModelFactory.java:11)
       at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
       at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
       at org.koin.androidx.viewmodel.ViewModelResolverKt.get(ViewModelResolverKt.java:23)
       at org.koin.androidx.viewmodel.ViewModelResolverKt.resolveInstance(ViewModelResolverKt.java:12)
       at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel(ScopeExtKt.java:86)
       at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel(ScopeExtKt.java:72)
       at org.koin.androidx.viewmodel.ext.android.ViewModelStoreOwnerExtKt.getViewModel(ViewModelStoreOwnerExtKt.java:68)
       at org.koin.androidx.viewmodel.ext.android.ViewModelStoreOwnerExtKt.getViewModel$default(ViewModelStoreOwnerExtKt.java:58)
       at my.package.name.FirstActivity$special$$inlined$viewModel$default$1.invoke(FirstActivity.java:75)

我怀疑这是因为有时 koinApplication 没有时间自行设置,但由于这种情况很少见,我无法重现该问题。

this stack question 的回答中,开发人员创建了一个ContentProvider 来实例化koinApplication。我已经尝试过了,到目前为止一切都很好(虽然,我只会在几个月后知道),但这真的是要走的路吗?必须为此创建内容提供者似乎有点过头了。

谁能阐明我们应该在哪里实例化本地KoinApplication

【问题讨论】:

  • 我不能说我自己已经完成了这个,但是堆栈跟踪表明视图模型没有在你的模块中设置,所以你可能想在问题中包含这些。此外,鉴于您的类的命名,您可能希望使用 by sharedViewModel 委托而不是 by viewModel
  • 另外——根据你的实际目标,你可能会发现使用 Scopes 是一条阻力较小的路径——仍然允许你使用传统的全局 startKoin 并提供我认为你的封装寻找insert-koin.io/docs/reference/koin-android/scope
  • @lase 视图模型在模块中,否则它根本无法工作。关于by sharedViewModelby viewModelthe docs are pretty clear about it的使用。它是一个库,打包为依赖项,并在不同的应用程序中使用,这一事实使得 Scopes 的使用变得更加棘手。也许我做错了,但我无法让使用和不使用 Koin 的应用程序很好地处理它们。我很想看到一个例子来说明它是如何工作的。

标签: android kotlin koin


【解决方案1】:

谁能阐明我们应该在哪里实例化本地 KoinApplication?

您应该在应用程序级别的类中执行此操作,例如,这就是我在应用程序类 onCreate 中的内容

startKoin {
            androidLogger(Level.ERROR)
            androidContext(this@VeroApp)
            modules(AppModules.modules) <-- list of defined koin modules
        }

我不太确定本地 KoinApplication 接口的使用。我知道例如 AppCompatActivity 是开箱即用的支持,你可以做一个而不扩展任何东西

private val sharedViewModel by viewModel<MySharedViewModel>()

【讨论】:

  • 我编辑了这个问题,因为似乎不清楚我的库是否已分发并用于不同类型的应用程序。有些使用 Koin,有些则不使用。我使用上下文隔离的原因是为了避免冲突。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
  • 1970-01-01
  • 2017-08-28
  • 2023-04-01
  • 1970-01-01
  • 2022-07-31
相关资源
最近更新 更多