Closed ataulm closed 5 years ago
It crashes if you try to go into the same activity multiple times. E.g. open a film, then press back and open a film.
Similar issue if you rotate the screen.
org.koin.core.error.DefinitionOverrideException:
Already existing definition or try to override an existing one:
[type:Factory,primary_type:'com.muvi.film_detail.FilmDetailViewModel']
Had a quick look. It's because we're loading modules with the same types defined without unloading them in between:
Feed --click film--> FilmDetail (1) --press back--> Feed --click another film--> FilmDetail (2)
Even though FilmDetail (2)
is a new Activity, we're calling loadKoinModules(feedModule)
again, which loads definitions into Koin that already exist, e.g. the FilmDetailViewModel
factory bean.
There's a few way I can see to solve this but I'm not sure which is correct :grimacing:
We load the modules in onCreate. So we can unload them in onDestroy. This is what I did in the PR that I'm about to open, but it's not a good solution:
FilmDetail (1) --click actor--> ActorDetail --click another film--> FilmDetail (2)
We'll still get the crash, because we never called onDestroy
for FilmDetail (1)
.
So this one should work, but I'm unsure what the cost of loading and unloading modules are :sweat_smile:
fun reloadKoinModules(vararg modules: Module) {
unloadKoinModules(*modules)
loadKoinModules(*modules)
}
The benefit of this one is that we can define a public function for our project and it's a single line swap whenever we load modules:
- loadKoinModules(feedModule)
+ reloadKoinModules(feedModule)
Where would this live? We'd probably have to introduce that core module that things depend on for utils :grimacing:
Mario takes this approach here.
Each Activity/Fragment where we load the module would instead call a top-level function in the file.
private val loadFeature by lazy { loadKoinModules(feedModule) }
private fun injectFeature() = loadFeature
internal class FeedFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
...
injectFeature() // instead of `loadKoinModules(feedModule)`
}
This one has more boilerplate per injection site.
Modules never get unloaded. Does this mean that we're keeping a reference to everything that we inject? :thinking: Or is it just that we're keeping how to build these things (the definitions, factories etc) which is less of an issue.
I think Koin ought to handle this for us :thinking: Or failing that, allow us to check if a module or definition is loaded.
ah we can also set a module-wide option (or on individual factories) to allow overriding definitions.
I set this instead; I think this should only be an issue if we define two or more types with different implementations (or behaviour) which I don't think will ever be the case :thinking: