问题
I am trying to understand dagger2 and implement in my app. I have read a lot about its benefits. Unless and until I understand it completely, I cannot get the benefits of it in my app.
I have understood @Module and @Inject. The one that confuses me is @Component. I have few questions related to that.
Module provides object instances and Inject uses it. Why do we need component in between? Is it really necessary to bridge the gap? Can we have empty Interface components without any methods?
Is constructor really necessary for module class? If there is no constructor in module class, Can we initialize module class using empty constructor?
Why can't we directly instantiate module class and build dependency graph instead of creating component and then initializing it?
I have seen only two kinds of methods in component interface so far
a. void inject(Activity/Service/Fragment); - Why do we need to provide an instance of activity or service or fragment to this method? why can't we have something like this -
void inject(); - Will the Component still generate dependency graph?
Can we inject from some other class other than activity or service or fragment something like this -
void inject(DataManager dataManager);
What If DataManager was a singleton instance?
b. Retrofit getRetrofit(); What is the difference between this method and above method? Why does not this take any input parameters?
I read that @Singleton is just a scope in dagger. How can we actually create a singleton object that lives for lifetime of the application?
Let's suppose there is a DataManager instance that I want to build using dagger. It is having only one dependency. I wrote a module class and a component interface for that. If I want to use this in let's say MainActivity, i use it as
@Inject DataManager dataManager;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
DataManagerComponent.Builder().DataManagerModule(new DataManagerModule()).build();
}
I want to use this datamanager in many other activities and I don't want it to be singleton. I want to keep it to the current activity scope where I use it. So I will use
@Inject DataManager dataManager;
to get that instance. Should I write
DataManagerComponent.Builder...........
in each and every activity oncreate() where I use @Inject DataManager dataManager? If I have to write that, Will it not create more boilerplate code than simply using
DataManager dataManager = new DataManager();
Let's suppose there are 4 objects and they are dependent on each other like D dependent on C, C dependent on B etc.
D -> C -> B -> A
Let's suppose I have written module class and provides method for all 4. If I try to inject D in any ActivityA like
@Inject D d;
Will C, B, A instantiated automatically?
Let's suppose in ActivityB I just need to inject B. If I inject B like
@Inject B b;
Will dagger create B and A again? Or will it use the ones which are already created ?
I appreciate if someone takes time to answer all my questions. I don't expect detailed answer. It is fine if it clarifies the concept. Looking forward for the response. Thanks in advance.
回答1:
This feels more like spoon feeding. I'll try to give you as much as information I can.
1 -> Module provides object instances and Inject uses it. Why do we need component in between? Is it really necessary to bridge the gap? Can we have empty Interface
components without any methods?
One of the basic principles of good code is; SOLID. Which brings us to coding to Interface principle the I in S.O.L.I.D.
Dagger
Components are the interfaces
it would generate the boilerplate code
for you; also It helps me documenting my object graph.
2 -> Is constructor
really necessary for module class? If there is no constructor
in module class, Can we initialize module class using empty constructor
?
In module class the constructor
is mainly used for External Dependencies. You can choose not to have one. Here you can call your component and directly say MyComponent.create()
3 -> why can't we directly instantiate module class and build dependency graph instead of creating component and then initializing it?
This will be like not using dagger
. Before dependency injection came into the existence developers could still follow the SOLID principles. however with Dagger
like frameworks It forces developers to think in decoupling the implementations.
4 a -> *void inject(Activity/Service/Fragment);
- Why do we need to provide an instance of activity or service or fragment to this method? Why can't we have something like this -
void inject(); - Will the component still generate dependency graph?
Can we inject from some other class other than activity or service or fragment something like this -
void inject(DataManager dataManager);
What if DataManager
was a singleton instance
?*
You need to mention the target in Dagger
. It can't be interface
, Object
can be singleton
it doesn't matter.
4 b -> Retrofit getRetrofit();
What is the difference between this method and above method? Why does not this take any input parameters?
This is definition of component. If you use constructor injection and let says if you change the number of input parameters you wouldn't have to go and change the code every place. Dagger
will take care of it.
Above code I believe is part of component definition so when you do component dependencies it will help you to expose it to outer graph
5 -> I read that @Singleton
is just a scope in dagger
. How can we actually create a singleton object
that lives for lifetime of the application?
The Thumb rule is in you module if you give a scope and create that component just once then It would be there for the life time. Generally one with application scope components are created in the Application class of your APP.
6 -> *Let's suppose there is a DataManager
instance that I want to build using dagger. It is having only one dependency. I wrote a module class and a component interface
for that. If I want to use this in let's say MainActivity
, I use it as
@Inject DataManager dataManager;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
DataManagerComponent.Builder().DataManagerModule(new DataManagerModule()).build();
}
I want to use this datamanager
in many other activities and I don't want it to be singleton. I want to keep it to the current activity scope where I use it. So I will use
@Inject DataManager dataManager;
to get that instance. Should I write
DataManagerComponent.Builder...........
in each and every activity oncreate()
where I use @Inject DataManager dataManager
? If I have to write that, Will it not create more boilerplate code than simply using
DataManager dataManager = new DataManager();*
Here You should not give any scope to the datamanager
provider and then every time u say @inject datamanager
it would come as different object instance even if your component is singleton
scope.
7 -> *Let's suppose there are 4 objects and they are dependent on each other like D dependent on C, C dependent on B etc.
D -> C -> B -> A
Let's suppose I have written module class and provides method for all 4. If I try to inject D in any ActivityA
like
@Inject D d;
Will C, B, A instantiated automatically?
Let's suppose in ActivityB
I just need to inject B. If I inject B like
@Inject B b;
Will dagger
create B and A again? Or will it use the ones which are already created ?*
It will be create if the injection is via constructor or else you've to use members injector.
Please go over YouTube tutorials
of twisted equations for dagger2
. That has helped me understand Dagger2
.
Do vote if you this helps you.
来源:https://stackoverflow.com/questions/45167015/not-able-to-understand-dagger-dependency-injection-concepts-dagger-2-on-androi