ComponentDispatcher
It is important to have your Dagger implementation to be optimised in order to create a clear separation between features. And every application, library or feature mostly wants to keep instances for as long as Application lifecycle. To achieve that, we create one big component to keep every instance in it and store that in Application class. But this already blocks having separated features!
More information about the details on the problem and this implementation, please read the post: https://medium.com/@yahyabayramoglu/building-features-by-independent-dagger-components-f634e55b9f07
Usage
1. Add library dependency to your build.gradle file:
dependencies {
api 'com.yayandroid:componentdispatcher:x.y.z'
}
Suggested; Add it into your core module and compile it as api
so that every other feature modules depending on core can use it.
2. Create ComponentGenerator
instances. CoreComponentGenerator
is not mandatory but if you want to share some instances from core module to your feature modules you need to define it as well.
class SampleCoreComponentGenerator : CoreComponentGenerator<YourCoreComponent>() {
override fun generate(): YourCoreComponent = // Create your component here.
}
class Feature1ComponentGenerator : FeatureComponentGenerator<YourFeatureComponent>() {
override fun generate(coreComponent: YourCoreComponent?): YourFeatureComponent = // Create your component here.
// Please note, if you don't create an implementation of `CoreComponentGenerator` coreComponent will be null here.
}
3. Define the CoreComponentGenerator path and create a string-array that contains keys for feature generators and define it in core module AndroidManifest
.
<application>
<meta-data
android:name="@string/component_generator_features"
android:resource="@array/component_generators" />
<meta-data
android:name="@string/component_generator_core"
android:value="com.yayandroid.componentdispatcher.sample.base.SampleCoreComponentGenerator" />
</application
component_generator_features
and component_generator_core
is required by the library. But for the rest of the features, library will use the given array as keys to the ComponentGenerator
implementations.
4. Initialize
class SampleApplication : Application() {
private lateinit var componentDispatcher: ComponentDispatcher
override fun onCreate() {
super.onCreate()
componentDispatcher = ComponentDispatcher(this)
}
fun getComponentDispatcher() = componentDispatcher
}
5. Get your component right away!
val componentDispatcher = (application as SampleApplication).getComponentDispatcher()
val feature1Component = componentDispatcher.get<Feature1Component>()
You can create an extension property for componentDispatcher like it is done in sample application.
Disclaimer
meta-data
approach is chosen because Android provides manifest merge and that would allow us to collect all the required ComponentGenerators on runtime. This approach can be still improved, but it can be considered as a conceptual work to split modules and dependencies.