在基本片段中处理 Koin(模块已加载错误)

Handle Koin in base fragment (Module already loaded error)

我有一个基本片段和另外 2 个片段,例如扩展基本片段的片段一、片段二。

abstract class BaseFragment(): Fragment(){
    init{
        loadKoinModules(listOf(sampleModules))
    }

    override fun onDestroyView() {
        super.onDestroyView()
        unloadKoinModules(listOf(sampleModules))
    }
}

当我登陆 fragmentOne 时,koin 模块已加载,一切正常。我从 fragmentOne 导航到 fragmentTwo,在 unloadKoinModules 之前再次调用 loadKoinModules。我认为 fragmentOne 中加载的模块仍然存在,并且在为 fragmentTwo 加载模块之前不会被删除。加载和卸载 koin 模块的正确方法或生命周期是什么?

module 'org.koin.core.module.Module@87380fe' already loaded!
module 'org.koin.core.module.Module@cef805f' already loaded!

快速修复

abstract class BaseFragment(): Fragment(){
    init{
        // Making sure we do not get "module already loaded" error
        unloadKoinModules(listOf(sampleModules))
        loadKoinModules(listOf(sampleModules))
    }

    override fun onDestroyView() {
        super.onDestroyView()
        unloadKoinModules(listOf(sampleModules))
    }
}

没有办法解决这个问题,因为 init 首先被调用,然后是 Fragment2 的 onCreateView,然后是 Fragment1 的 onDestroyView(并不总是被调用,取决于 Fragment2 的方式介绍到碎片堆栈)。

就个人而言,我会从片段中删除模块加载。但是我不确定你为什么需要卸载它们。

稍微好一点的方法

我首先想到的是:

  1. 您创建一个新的 Activity 基于 class;
  2. onCreate 的 class 中加载模块;
  3. 你显示你需要的片段,上下导航this activity;
  4. 的片段返回栈
  5. 调用 Activity#onDestroy 时 - 卸载模块
class MyActivity: Activity {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loadKoinModules(listOf(sampleModules))

        // load the first fragment
    }

    override fun onDestroy() {
        super.onDestroy()
        unloadKoinModules(listOf(sampleModules))
    }
}

如何做得更好? (如果卸载可以去掉)

首先,确定你真的要卸载这些模块。为什么不让它们只加载一次然后离开?自己决定。

Koin 模块只能加载一次。一旦它们被加载,这些模块将在整个应用程序中可用。这意味着您不能加载同一个模块两次 - 没有必要。

在 Koin 官方示例中有一个专门针对 Android:

class MyApplication : Application() {
  override fun onCreate(){
    super.onCreate()
    // start Koin!
    startKoin {
      // declare used Android context
      androidContext(this@MyApplication)
      // declare modules
      modules(myModule)
    }
  } 
} 

正如我们所见,模块是从 Application class 加载的。当您的应用程序是 运行 时,您只能有一个 Application class 的有效实例。这意味着 onCreate 不会被调用两次,因此从 Application#onCreate.

加载模块是安全的

或者,您可以从 Activity class 的 onCreate 加载模块,如上所述。 但请注意,activity 可以在应用程序的生命周期内多次重新创建。