I am looking for some guidance on the best code structure for dagger in multi module android apps.
Lets say we have featureModuleA and featureModuleB, both of which depend on commonCodeModule.
Id like commonCodeModule to provide some dependencies using dagger, to both featureModuleA and featureModuleB.
Would it be better to expose those dependencies using a Component from commonCodeModule, therefore both feature modules need to create that component at injection time
OR
is it better to expose those dependencies by allowing both feature modules to use the Module residing in commonCodeModule?
Do they need to share the instances from the graph of the commonModule? If yes, then it would be cleaner to use component dependency. Component approach is a bit messier than just exposing ready-made modules, but you more control over lifecycle of objects in the component.
In addition, if you have smaller set of dependencies coming from commonModule you can seed them using #BindsInstance in your featureModule components. Binding instances will deprive your feature module components of knowledge about any kind of component coming from the commonModule.
My two cents on exposing modules: If featureModuleA and featureModuleB can create their own instances of the classes in the commonModules, then you can expose Modules.
I have a question. I have an application that I wrote by extracting data from Api. And I want to add dependency injection to it. Which library will work best and why? How should I choose?
In Android there are multiple libraries to support dependency injection here are few of most used ones by developers.
The ones provided by google are Dagger and Hilt. But they have a bigger learning curve compared to other DI libraries. Still I would recommend to you these in your project.
Hilt is the latest counterpart and is a written over the existing Dagger DI and comes with all the abilities of Dagger hence it is recommended from now on over dagger since it provides a standard way to use DI in your application which was missing in Dagger.
Check out about Dagger from this link
Check out about Hilt from this link
Both the above DI libraries automatically generates code that mimics the code you would have written manually to provide dependency. The code is generated at compile time and therefore if there comes any issue with providing dependency it will be shown at compile time hence avoiding runtime issues regarding fulfilling dependencies.
There are Kotlin specific dependency injection libraries too such as Koin which is more easy to learn and implement compared to Dagger.
Check out about Koin from this link
Koin is usually considered for small to medium sized projects while Dagger and Hilt is considered for medium to large sized projects.
Dagger hilt library is best for dependency injection very less code for injection you can simply inject anything also no need to provide any view model factories for your view models
Square Inc. has presented it's internal modular architecture at Droidcon SF'19:
https://www.droidcon.com/media-detail?video=380843878
However, I'm a bit confused with some bullets. Could you please help me?
Why do they actually need :wiring modules? I find it adding complexity:
you get extra gradle module for each new feature
you have to make a sort of global injection into your Fragments somewhere in :app, because Fragments defined in :impl modules cannot access it's DaggerComponent, which is defined in :impl-wiring modules. :impl doesn't depend on :impl-wiring, because the dependency is reversed.
you cannot have an Android Dynamic Feature modules, because they should know about it's DaggerComponent in order to inject it's Fragment. But there is no way to do such injection from :app module, which is base-module for Dynamic Features.
so why :wiring modules at all?
One can merge :impl and :impl-wiring, or :fake and :fake-wiring together to eliminate all the issues mentioned above. And also, in :demo-apps one could just have a dependency on either :impl or :fake``, and not on :impl-wiring(or:fake-wiring```).
The creation of this type of modules is to separate even more. With this you generate an abstraction of the type of component you use (koin, dagger) and how. If the project is large, it makes sense to do it.
Currently I generate the following flow of dependencies between modules:
WARNING: Check the directionalities well.
:feature-A:open <- :feature-A:impl -> :feature-A:impl-wiring
:feature-A:impl-wiring -> :feature-A:impl, :feature-A:open
:app -> :feature-A:open, :feature-A:impl-wiring
I'm still not sure if app should depend on open and impl-wiring, or which app should only depend on open and open from impl-wiring.
Eventually, I came up with the following solution:
each feature consists of the following gradle-modules:
api
impl and fake
data:api
data:impl1 ... data:implN and data:fake
data:wiring
ui
demo
So, here api, impl and fake as usual, but I've my data layers separated. I bought myself that I need multiple different implementation of data layers sometimes, for example - if I develop Stock-Charts App, I could rely on Finnhub Open API or MBOUM API or provide fake implementation.
Thus I have data:api, data:implX. Indeed, data:api defines FeatureRepository interface (one or many) and data:implX provides actual implementation for them. In order to bind interface and implementation, I use data:wiring, which defines Dagger modules and component(s). In addition, I keep the same package names within each data:implX module in order to "write-once" the data:wiring module. And to replace one implementation with another, I just change a single line in data:wiring/build.gradle which states a sort of:
implementation project(":data:implA")
to
implementation project(":data:implB")
Also, to break the confusion mentioned in my original question, I introduce ui module, which contains some Views of a particular feature. Fragments go in demo (a standalone app to test feature) or in ui, they refer to viewModel which have some bindings ctor-injected from Dagger component of a feature. But the UI and library are separated here. Fragment instantiates a dedicated Dagger component that uses component dependencies to refer to feature's library bindings, such as interactor or repository etc.
So, to wrap up - separation between UI and business logic implementation (a "library") for each feature makes it possible to solve the issue. Feature's api declares an entry point to it's functionality as a library, and it's global access via Dagger multibindings from :app. So it can be used further in any :demo, :ui and :dynamic-feature.
I am using dagger2 in my application. I am confused which one is more efficient.
While using dependent component you can access the limited dependencies which are declared downstream in app level component
On the other hand, subcomponent will give access to all dependencies of app level component.
I’m working on a project that is based on the GithubBrowserSample demo application that’s on the Android Architecture Repo on Github.
So far, I was able to inject dependencies to my App, activities and fragments and ViewModels. Also I was able to add more Modules; right now I use two, one for Shared preference and the other a NetModule that has all the mumbo jumbo related to Retrofit/OkHttp.
But here’s the catch: currently the demos that I found that shows how to implement the Retrofit/OkHttp module has a static base URL, which doesn’t work for me since that information is available until the User provide it on the Login section…
Digging around I found that one solution is to create a Submodule (StackOverflow post) with a given Scope Instantiate the component inside my Activity/Fragment. But because I’m using Dagger 2.11 for Android to perform the injection, I have no idea how to do so…
Is there an example that I can look around, or should I give up on this path and take the OkHttp interceptor to change the URL?
Thanks in advance.