简体   繁体   中英

Handle Koin in base fragment (Module already loaded error)

I have a base fragment and 2 more fragments eg fragmentOne, fragmentTwo that extend the base fragment.

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

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

When I landed on fragmentOne, koin modules are loaded and everything is fine. I navigate from fragmentOne to fragmentTwo, loadKoinModules is called again before unloadKoinModules. I think the loaded modules in fragmentOne still exist and are not removed before loading the modules for fragmentTwo. What is the correct way or lifecycle to load and unload the koin modules?

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

To fix it fast

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))
    }
}

There is no way around this because init called first, then onCreateView of Fragment2, then onDestroyView of Fragment1 (and not always it is called, depends on how Fragment2 is introduced to the stack of fragments).

Personally, I'd remove module loading from fragments. But I'm not sure why you need to unload them.

A slightly better way

What comes first to my mind is:

  1. You create a new Activity based class;
  2. Inside of this class from onCreate you load modules;
  3. You show the fragments you need, navigate up and down the back stack of fragments of this activity ;
  4. When Activity#onDestroy is called - unload modules
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))
    }
}

How to do it better? (if unloading can be removed)

First of all, make sure you really want to unload these modules. Why not have them loaded only once and leave? Decide for yourself as you see fit.

Koin modules must be loaded only once. Once they are loaded these modules will be available throughout the application. It means you cannot load the same module twice - there is no need for it.

Amongst Koin official examples there is a one specifically for the Android:

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

As we can see modules are loaded from the Application class. You can have only one valid instance of Application class when your app is running. It means onCreate will not be called twice, so it is safe to load modules from Application#onCreate .

Alternatively, you can load modules from onCreate of your Activity class, as mentioned above. But be aware that activity can be recreated multiple times during a lifecycle of the application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM