Referencing a component with different scope - Android Dagger 2 - android

So I've got this scenario in Android where I have AppComponent, which is a #Singleton. One of my modules, which needs to have a custom scope, #ActivityScope I'm calling it, provides an object which it instantiates and whose constructor requires another object which is provided by AppModule. This is a problem, because when I try to reference AppModule from this module I get an error because one is scoped as #Singleton and the other one as #ActivityScope.
I'm having trouble trying to apply what I read online about subcomponents, which seem the way to go, to my particular case. Can I get any hint?

Related

Dagger2 dependent-component vs subcomponent

What's the difference between Subcomponents and Dependent-Components with specific scope in action? What's pros or cons of every one?
My Story: Recently I decided to stop using dagger-android and completely switched to traditional dagger for dependency injection in the whole of my project. Do you have any recommendations for creating component/subcomponent per fragment/activity?
If you create sub-component, all your component's dependencies will get available in your sub-component too.
You can access sub-component only via parent component instance.
The sub-component, scope is considered smaller than that of its parent component. So, your parent component and sub-component can't use the same scope annotation.
If you create dependent-component, then you have to explicitly expose dependency in your parent component. Then only, the child-component can use it.
You can use dependent-component directly, but you'll have to provide instance of parent component to build a dependent-component.
Get more details from these videos: https://www.youtube.com/playlist?list=PLrnPJCHvNZuA2ioi4soDZKz8euUQnJW65
Just watched an interview, and the guy said that the downside of Subcomponents is that if you change anything inside them, the whole AppComponent gets regenerated (and in big codebases that can be very slow), while Dependent-Components are separate entities.
Will research that more and correct the post if it is wrong.

With Dagger 2, is it possible to inject on a same class from different subcomponents or from different components?

It seems to be impossible but I can't find it written explicitly. Is there a clear reason for that ?
Thanks
That's not possible. A component can either inject everything at once or the compilation will fail with a cannot be provided error, listing what it's missing.
After all you can't partially call a constructor (if using constructor injection) and also partially injecting fields would be rather indeterministic about which objects were injected when, how, or with which scope. If both components could supply a dependency, which should provide it? Do you create and inject the object twice? What if another object depends on it in the other component? It would create more confusion than any good it could do and provide a source for a lot of errors and unexpected behavior.
Only one component can be used to inject inside a given class. You can have several subcomponents dependencies installed on it though.

Dagger 2 bindings delegation with subcomponents

I have a little problem with designing DI architecture of my app. I am using Architecture Components ViewModels and I was inspired how to provide ViewModels via Dagger in their own GitHub repository .. I want to create scoped component/module for example for product detail that would provide ViewModels/Repositories and other stuff dependent on that single product.. problem is that all ViewModels are provided from the same ViewModelModule as in given example. But ProductViewModel needs ProductRepository that is provided from scoped subcomponent ProductModule. And apparently thats not possible because Dagger throws error at build time that I need to provide ProductRepository with #Provides annotation.
Ok so I thought that I would provide ProductViewModel in my ProductModule but then it crashes at runtime, because provider of my ViewModel can't be found in this method
Is it possible at all to have this architecture or do I need to redesign it to not use the same method as Google in their sample?
I was able to solve a similar problem by removing the #Singleton annotation on the ViewModelProvider.Factory subclass.
It shouldn't matter whether the factory is a singleton or not; it's only a performance issue, really. I ended up using #Reusable instead, which tells Dagger that the factory instance can be safely reused if needed, but without the restrictions of a specific scope.

Dagger 2: Providing dependencies in Application Module vs injecting them

I was trying to add Dagger 2 to my android app.
As far as I understand, Dagger will construct my object(which I am trying to inject) as long as its' dependencies are provided(in a Module) or they are injected using some form of injection(constructor/method).
I would like to know if there's a distinction between when a dependency should be provided in a Module(say Application Module) vs when its' injected using a constructor injection, and if there is any rule of when I should do which?
Both are the same. Constructor injection basically eliminates the need to write a provider method. As a rule of thumb, I mostly use it for classes with a no-args constructor for easy injection, like Util classes.
There's no difference really. As long as Dagger knows how to construct an instance, that's all that matters.
The reason there are two ways to do it is that you don't always have the ability to use constructor injection, for instance if the class is part of a library that you are using but which you don't have the source (and so you can't add #Inject on one of the constructors).

Singletons in Dagger 1.x

When using Dagger, I found that I'm getting multiple instances of a singleton when I inject it wherever I need it. I've annotated the class and the provides method with #Singleton. Can anyone think of why this is happening?
Edit:
If it helps, I have followed the same structure for my app as the sample application in Dagger's GitHub (https://github.com/square/dagger/tree/master/examples/android-activity-graphs). I'm trying to get the Singleton in the base activity and a couple of third party classes provided using #Provides at the custom Application class. Is it because I'm plus-ing modules at each activity to the original object graph?
(PS : I'm new to Dagger and DI in general, so I'll be grateful if you could provide an explanation so that I may learn. Thanks.)
#Singleton, in Dagger 1.x, acts differently than you might think. The JSR-330 spec definition in the #Singleton javadoc is "one per graph" and that is how Dagger interprets it.
So if you have something that is marked as #Singleton, and it is materialized in your application graph (as opposed to a shorter-lifetime graph), then you get one instance per application.
If you have an item annotated #Singleton that's in the modules you use to configure your activity graph (i.e., that is obtained from the part of a graph specified by a module used in the plus() operation) then you will get one-per-activity-graph.
If you need something to be once-per-application, you need to make sure it gets created as a part of the application graph. You can do this in one of two ways. Either explicitly provide it with an #Provides method from your application module(s), or you can list it as a one of the classes in #Module(injects=...) in an application module.
(If you do not mark it with #Singleton than you will get one per injection site.)
So remember, the graph created by plus() is seen as a separate graph that points to the graph from which it was spawned, and wraps it, can access instances within it, but is not the same graph.
Note - Dagger 2.x improves this, and supports custom scoping annotations, though the mechanism is similar, with one graph (component) per scope annotation, with a parent/child relationship between graphs of wider/narrower lifetimes

Categories

Resources