I have a several features modules. Each of them contains three modules that are :domain, :data and :ui. So my question is where should I store FeatureComponent? Obviously I will need it for all of three layer-modules for example to inject usecases to viewmodel, to inject apis to repository, etc. But then where to store this FeatureComponent? Or should I just create three component one layer each? What's the best approach here?
I thought that it is a good idea to store it inside domain module but obviously it isn't because then I may face some troubles with domain depend on android framework so. Any thoughts?
I think a dagger component should be stored by whatever instance is responsible for its lifecycle.
For example: The application class is responsible for the lifecycle of the application-wide (or singleton) dagger component.
Most repositories should be contributed to this application-wide dagger component, as you want them to be singleton probably.
Then for your feature-scoped dagger components, its lifecycle could for example be managed by an activity, so its the activity that stores that component, and exposes it to the fragments so they can inject their viewmodels. One side-note is that this approach is a little bit risky when enabling kill-activities and going out of and in to your app, a new activity would be created so possibly also a new feature-scoped dagger component, but thats probably not what you want. (we solved that by overriding onSaveInstanceState, and using that to cache the feature-scoped dagger component in the application, and restore that in the onCreate of the activity using an identifier that we store in the bundle)
What we have for example is an application scope, for which its component is managed by the Application class.
Then we have an environment scope, for which its component is managed by a custom EnvironmentRepository (that resides as a singleton within the application scoped component). This EnvironmentRepository is responsible for providing the environment dagger component. Switching environments (e.g. going from acceptance to production) is a breeze, as all environment specific configuration values are installed in the environment component by the EnvironmentRepository.
We do the same trick for the user scoped dependencies, there is a UserRepository (installed in the Environment scoped component), which lets us switch users easily.
All code to do data persistence is provided down the layers of dagger components, so when you are writing some CustomerDataRepository, and you want to persist the result, you could inject a UserScoped shared preference instance, so it does not collide with the user data stored for another user or another environment.
I would also advise you to look at Anvil (which I have no affiliation with), that makes organising components, subcomponents, modules, contributing to the correct (sub) component in multi-modular apps a breeze.