I am using Dagger2 in my android application, I have two component in my application. First is global for entire application and second is specific to activity instance.
NetComponent.java
#Singleton
#Component(modules = {AppModule.class, NetModule.class})
public interface NetComponent {
void inject(AuthenticationActivity authenticationActivity);
void inject(PaymentActivity paymentActivity);
}
ValidationComponent.java
#Singleton
#Component(modules = {ValidatorModule.class})
public interface ValidationComponent {
void inject(Activity activity);
}
AppModule.java
#Module
public class AppModule {
private Application application;
public AppModule(Application application) {
this.application = application;
}
#Provides
#Singleton
Application providesApplication() {
return application;
}
}
NetModule.java
#Module
public class NetModule {
#Provides
#Singleton
SharedPreferences providesSharedPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}
#Provides
#Singleton
Cache provideOkHttpCache(Application application) {
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(application.getCacheDir(), cacheSize);
return cache;
}
#Provides
#Singleton
Gson provideGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
#Provides
#Singleton
OkHttpClient provideOkHttpClient(Cache cache) {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newBuilder()
//.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.cache(cache)
.build();
return okHttpClient;
}
#Provides
#Singleton
#Named("authRetrofit")
Retrofit provideAuthRetrofit(Gson gson, OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(PAYMENT_SERVICE)
.client(okHttpClient)
.build();
return retrofit;
}
#Provides
#Singleton
#Named("paymentRetrofit")
Retrofit providePaymentRetrofit(Gson gson, OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(LOGIN_SERVICE)
.client(okHttpClient)
.build();
return retrofit;
}
}
ValidatorModule.java
#Module
public class ValidatorModule {
private final Activity activity;
public ValidatorModule(Activity activity) {
this.activity = activity;
}
#Provides
com.mobsandgeeks.saripaar.Validator providesValidator() {
return new com.mobsandgeeks.saripaar.Validator(activity);
}
}
AppApplication.java
public class AppApplication extends Application {
private NetComponent mNetComponent;
#Override
public void onCreate() {
super.onCreate();
mNetComponent = DaggerNetComponent.builder()
.appModule(new AppModule(this))
.build();
}
public NetComponent getmNetComponent() {
return mNetComponent;
}
}
AuthenticationActivity.java
public class AuthenticationActivity extends BaseActivity implements View.OnClickListener, Validator.ValidationListener {
#Inject
Validator validator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
((AppApplication) getApplication()).getmNetComponent().inject(this);
ValidationComponent validationComponent = DaggerValidationComponent.builder()
.validatorModule(getValidatorModule())
.build();
validationComponent.inject(this);
...
// apply click and validation listeners
validator.setValidationListener(this);
}
}
protected ValidatorModule getValidatorModule() {
return new ValidatorModule(this);
}
It is generating ValidationComponent but not DaggerNetComponent
Above are my module, components of my application. When I am compiling and building a application then I am getting below errors -
Error
Information:Gradle tasks [clean, :app:generateDebugSources, :app:mockableAndroidJar, :app:prepareDebugUnitTestDependencies, :app:generateDebugAndroidTestSources, :app:compileDebugSources, :app:compileDebugUnitTestSources, :app:compileDebugAndroidTestSources]
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\AppApplication.java
Error:(24, 48) error: cannot find symbol class DaggerNetComponent
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\login\AuthenticationActivity.java
Error:(35, 48) error: cannot find symbol class DaggerValidationComponent
Error:(39, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\checkout\PaymentActivity.java
Error:(28, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\dashboard\DashboardActivity.java
Error:(32, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\shopping\ScanBarcodeActivity.java
Error:(41, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\ui\GetStartedActivity.java
Error:(27, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\dagger\component\NetComponent.java
Error:(34, 10) error: com.mobsandgeeks.saripaar.Validator cannot be provided without an #Inject constructor or from an #Provides- or #Produces-annotated method.
com.icici.iciciappathon.login.AuthenticationActivity.validator
[injected field of type: com.mobsandgeeks.saripaar.Validator validator]
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
Information:BUILD FAILED
Information:Total time: 11.373 secs
Information:9 errors
Information:0 warnings
Information:See complete output in console
The general statement here is that Dagger doesn't generate classes when it encounters an error, usually when you're doing something impossible in your binding graph. That's the case here.
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\dagger\component\NetComponent.java
Error:(34, 10) error: com.mobsandgeeks.saripaar.Validator cannot be provided without an #Inject constructor or from an #Provides- or #Produces-annotated method.
com.icici.iciciappathon.login.AuthenticationActivity.validator
[injected field of type: com.mobsandgeeks.saripaar.Validator validator]
I agree with azizbekian that the problem is that you are trying to inject the Validator from within AuthenticationActivity, and telling NetComponent to try to do so without instructing it how to do so (in ValidationModule).
In the code you've posted, there isn't a reason for NetComponent to inject AuthenticationActivity; there's nothing for it to provide. So you can delete these two lines and be done:
// In NetComponent
void inject(AuthenticationActivity authenticationActivity);
// In AuthenticationActivity
((AppApplication) getApplication()).getmNetComponent().inject(this);
However, it's also possible that you've simply not shown us the NetComponent dependencies you need in AuthenticationActivity. In that case, you're going to need to combine the object graphs, either through subcomponents or component dependencies. You'll still need to delete the two lines listed above, because under no circumstance does NetComponent have the dependencies it needs to inject AuthenticationActivity.
Subcomponents
To do so with subcomponents, simply make a builder on NetComponent through which you get your ValidationActivity. You're welcome to provide a scope, but you don't necessarily need one, and I think it might be confusing to add that into the mix. At that point, your ValidationComponent will have access to all the bindings in your NetComponent AND all of the bindings listed in ValidationComponent. This is effectively identical to azizbekian's answer, though notably this is through subcomponents, not component dependencies. I'll talk about component dependencies in a moment.
// After removing the inject(AuthenticationActivity) call, add this to NetComponent
ValidatorComponent validatorComponent(ValidatorModule validatorModule);
// And call the implementation from AuthenticationActivity
((AppApplication) getApplication()).getmNetComponent()
.validatorModule(new ValidatorModule(this))
.inject();
You'll also need to switch ValidationComponent from #Component to #Subcomponent, and remove the #Singleton instance (which makes sense because you're creating a new one for every AuthenticationActivity instance Android creates.
Effectively, this turns NetComponent into a factory for ValidationComponent instances. Dagger generates the code for both at once, so ValidationComponent can access anything it needs from NetComponent automatically. However, this way it is impossible to generate code for each one separately, or to get a ValidationComponent without a NetComponent instance (except through including it in another component).
Component dependencies
Component dependencies work a little bit differently. They're freestanding components, so they can be generated separately and independently. Instead, you can pass in an interface (often but not necessarily another Dagger component like NetComponent), and every single no-argument method becomes an automatic provider into the other graph. This means, for example, that you could list specific dependencies available to ValidationComponent from NetComponent, add a dependencies={NetComponent.class} to your ValidationComponent definition, and then change your DaggerValidationComponent builder to call .netComponent(((AppApplication getApplication()).getmNetComponent()) to hook the exact instances up. (Similarly, you could do so with any implementation of that interface, whether Dagger generates it or not; this can help with testing.) You'll also need to remove the use of #Singleton, because Dagger would be very confused to have two separate components both claim to exist in singleton scope—one has to be created first, after all.
You haven't listed out the exact dependencies you're consuming out of NetComponent, so I don't have example changes I can show. However, for cases like this, I would recommend using subcomponents anyway; the bindings are more automatic, you likely won't benefit from the loose coupling you'd get from component dependencies, and you're closer to the design of Dagger's official Android support package so it's easier to migrate to that later.
In your onCreate() you have following piece of code:
((AppApplication) getApplication()).getmNetComponent().inject(this);
ValidationComponent validationComponent = DaggerValidationComponent.builder()
.validatorModule(getValidatorModule())
.build();
validationComponent.inject(this);
And you have declared that you are willing to #Inject a Validator instance.
Hence when getmNetComponent().inject(this) is reached, Dagger will try to inject that dependency, but it cannot find in that component, because it will be provided from ValidatorComponent (which will be executed later).
This is a situation, when you have to make use of subcomponents. Basically, your ValidatorComponent needs to see all dependencies provided by NetworkComponent and also add some of its own.
Following changes should be made:
NetComponent.java
#Singleton
#Component(modules = {AppModule.class, NetModule.class})
public interface NetComponent {
void inject(AuthenticationActivity authenticationActivity);
void inject(PaymentActivity paymentActivity);
ValidatorComponent validatorComponent(ValidatorModule validatorModule);
}
ValidationComponent.java
#YourCustomScope
#Subcomponent(modules = {ValidatorModule.class})
public interface ValidationComponent {
void inject(Activity activity);
}
AuthenticationActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((AppApplication) getApplication()).getmNetComponent()
.validatorModule(new ValidatorModule(this))
.inject();
}
YourCustomScope.java
#Scope
#Documented
#Retention(RUNTIME)
public #interface YourCustomScope {}
if you're using kotlin you have to add
apply plugin: 'kotlin-kapt'
in your build.gradle file
and alose use kapt instead of annotationProcessor in your dependencies
chage this :
implementation 'com.google.dagger:dagger:2.22'
annotationProcessor 'com.google.dagger:dagger-compiler:2.22'
implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.22'
to this:
kapt 'com.google.dagger:dagger-compiler:2.22'
implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22'
kapt 'com.google.dagger:dagger-android-processor:2.22'
Related
Im learning Dagger 2, i have noticed that in some examples there is a #Singleton in the module's methods and on other #Singleton on the Component's methods? What is the difference and what exactly a #Singleton annotation on a module's method and on an component's method mean?
Since you're a beginner, I highly recommend just trying stuff. Writing unit tests is easy enough, and it helps to understand and prove theories.
If you didn't already, read the User's Guide for some basic knowledge about dagger and scopes.
Annotating methods in components (provision methods) doesn't have any effect. You will have to annotate the class or providing method in a module. I want to quickly show how you can just quickly prove this yourself:
We have 2 Component, one using a scope #Singleton, the other one none:
#Singleton
#Component(modules = SingletonModule.class)
public interface SingletonComponent {
Object getObject();
}
#Component(modules = NormalModule.class)
public interface NormalComponent {
#Singleton
Object getObject();
}
With those components come 2 modules, one providing the singleton scoped object (same as the component) the other one just uses no scope:
#Module
public class SingletonModule {
#Provides
#Singleton
public Object provideObject() {
return new Object();
}
}
#Module
public class NormalModule {
#Provides
public Object provideObject() {
return new Object();
}
}
And now we just create a small test:
public class ComponentTest {
#Test
public void testSingletonComponent() {
SingletonComponent component = DaggerSingletonComponent.create();
Assert.assertEquals(component.getObject(), component.getObject());
}
#Test
public void testNormalComponent() {
NormalComponent component = DaggerNormalComponent.create();
Assert.assertNotSame(component.getObject(), component.getObject());
}
}
This test will succeed and prove that annotating methods in components doesn't do anything. Scoping objects in modules, or annotating the class itself when using constructor injection will result in the object being reused within the same scope / the same component.
Creating 2 components of the same scope will also lead to duplicate objects, as can be proven like this:
#Test
public void testTwoSingleonComponents() {
SingletonComponent component1 = DaggerSingletonComponent.create();
SingletonComponent component2 = DaggerSingletonComponent.create();
Assert.assertNotSame(component1.getObject(), component2.getObject());
}
Be sure to read some tutorials and be sure to try things out. The compiler will complain if you do things wrong! :)
I started using dagger 2.2 and the module methods in the Component builder are deprecated.
This is my Application component :
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(Application application);
}
And the Application module:
#Module
public class ApplicationModule {
Application application;
public ApplicationModule(Application application) {
this.application = application;
}
#Provides
#Singleton
Application providesApplication() {
return application;
}
}
Here is the generated class:
#Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class DaggerApplicationComponent implements ApplicationComponent {
private DaggerApplicationComponent(Builder builder) {
assert builder != null;
}
public static Builder builder() {
return new Builder();
}
public static ApplicationComponent create() {
return builder().build();
}
#Override
public void inject(Application application) {
MembersInjectors.<Application>noOp().injectMembers(application);
}
public static final class Builder {
private Builder() {}
public ApplicationComponent build() {
return new DaggerApplicationComponent(this);
}
/**
* #deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://google.github.io/dagger/unused-modules.
*/
#Deprecated
public Builder applicationModule(ApplicationModule applicationModule) {
Preconditions.checkNotNull(applicationModule);
return this;
}
}
}
How do I initialize the component if not with the ComponentBuilder?
You should read the description of why it is deprecated. If you are using an IDE like IntelliJ or Android Studio you can just select the method and hit Control + Q on Windows to read the Javadoc including the deprecation notice.
The Javadoc reads:
#deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://google.github.io/dagger/unused-modules.
And from this link you can see:
When the Dagger processor generates components, it only requires instances of modules and component dependencies that are explicitly needed to supply requests for a binding.
If all of a module’s methods that are used in the component are static, Dagger does not need an instance of that module at all. Dagger can invoke the static methods directly without a module.
If a module provides no bindings for a Component, no instance of that module is necessary to construct the graph.
It is safe to say that you can just ignore the deprecation. It is intended to notify you of unused methods and modules. As soon as you actually require / use Application somewhere in your subgraph the module is going to be needed, and the deprecation warning will go away.
It show deprecated because you are not using Component and module in your application by
#Inject
SomeObjectFromModule mSomeObject
if you are not injecting dependencies in your applications there is no use of initialising your component so dagger look for at least one usage
once you add these lines in any classes you want to inject views and then clean build and rebuild the project and your deprecation will be solved
It showing error when my Module have no #Provides method or the object that provide by Dagger is not used in app.
Example to remove deprecated module
Module
#Module
public class SecondActivityModule {
#Provides
Book provideBookTest() {
return new Book();
}
}
Activity
public class SecondActivity extends AppCompatActivity {
#Inject
Book test;
...
}
OR in Component
#Component(modules = SecondModule.class)
public interface SecondComponent {
void inject(SecondActivity activity);
Book getBookTest();
}
I have the same problem with host and I just want everyone has deprecated issue on Generated component builder class should check two things to save time:
1/ Correct dagger syntax for module, component also check carefully where you inject.
2/ Must have injection object (inject annotation and its object) in place you want to inject or else the dagger compiler cannot see where to use your module so some method will be deprecated.Just inject at least one module's provides to your injection place and re-compile the code, you won't have that issue anymore :)
you will get module method deprecated if you declare void inject(AppCompactActivity activity); in component class. instead of you have to use tight coupling like following void inject(MainActivity activity);and rebuild your project you will see, there is no deprecate method in module class
I have this component:
#Singleton
#Component(modules = OauthModule.class)
public interface OauthComponent {
void inject(LoginActivity a);
}
and the module:
#Module
public class OauthModule {
#Provides
#Singleton
Oauth2Service provideOauth2Service() {
return new Oauth2StaticService();
}
}
and this another component:
#Singleton
#Component(modules = LoggedUserModule.class)
public interface LoggedUserComponent {
void inject(LoginActivity a);
}
and I get this error:
Error:(15, 10) error: Oauth2Service cannot be provided without an
#Provides- or #Produces-annotated method.
If I change the LoggedUserComponent's inject method parameter to be another Activity, say AnotherActivity like this:
#Singleton
#Component(modules = LoggedUserModule.class)
public interface LoggedUserComponent {
void inject(AnotherActivity a);
}
compilation is ok. Why? Can't I have two components with the same inject signature?
I'm trying to understand how Dagger works so any help will be appreciated. Thanks.
Think of dagger as an object graph—which it actually is. You probably should not have 2 different components being able to inject the same object, other than for testing purposes (or if you want to include different behavior, not additional one).
If your LoginActivity depends on multiple modules, you should aggregate them in a single component, since as your error shows, dagger will fail if it can not provide all dependencies from a single component.
#Singleton
#Component(modules = {LoggedUserModule.class, OauthModule.class})
public interface LoggedUserComponent {
void inject(AnotherActivity a);
}
Looking at Oauth2Service, this could easily be something that multiple objects could use, so a higher scope could be adequate. In that case you should think about adding it with a #Singleton scope to your application component, or maybe create its own component with e.g. a #UserScope.
Then you would have to either make your LoggedUserComponent a #Subcomponent or declare this component a dependency using #Component(dependencies = OauthComponent.class) and providing a getter in OauthComponent for it. In both cases dagger would also be able to provide the dependency found higher in the graph, thus also resolving your error.
It's getting mad because you're saying you can inject into that class but you're not providing a class that it's expecting you to provide. You just need to add the OauthModule to your LoggedUserComponent. Try this
#Singleton
#Component(modules = {LoggedUserModule.class, OauthModule.class})
public interface LoggedUserComponent {
void inject(LoginActivity loginActivity);
}
Yes, I know this has been asked before, and yes, I know it is "by design".
But I'd like to do something like this:
#Component(modules = {RealmModule.class})
public interface RealmComponent {
Realm realm();
}
#Component(modules = {RepositoryModule.class})
public interface RepositoryComponent {
PersonRepository personRepository();
ScheduleRepository schedulesRepository();
}
#Component(dependencies = {RealmComponent.class, RepositoryComponent.class})
public interface AppDataComponent
extends RealmComponent, RepositoryComponent {
}
#ApplicationScope
#Component(dependencies = {AppContextComponent.class,
AppDataComponent.class,
AppDomainComponent.class,
AppPresentationComponent.class,
AppUtilsComponent.class})
public interface ApplicationComponent
extends AppContextComponent, AppDataComponent, AppDomainComponent, AppUtilsComponent, AppPresentationComponent {
void inject(CustomApplication customApplication);
void inject(DashboardActivity dashboardActivity);
}
However, what I get is unscoped, every time I inject a JobManager or a ScheduleRepository or anything else, I get a new instance. The only way I could "fix" that was this.
#Module
public class JobManagerModule {
private JobManager jobManager;
#Provides
public JobManager jobManager(Context context) {
if(jobManager == null) {
jobManager = new JobManager(context, new Configuration.Builder(context).networkUtil(
new WifiOrMobileNetworkUtil(context)).build());
}
return jobManager;
}
}
Not a fan.
So, how is one meant to structure and rip apart the dependency tree, without making one big gigantic über blob component that has every single module listed and every single provision method (instead of these "subcomponent" component dependencies)?
I tried using subcomponents for this, but then you have to provide every single module for the final ApplicationComponent.
I'm not sure what to do here. I tried specifying #Singleton for every first-level component and #SubcomponentScope for every AppDataLevelComponent, I also tried making a new scope for every single subcomponent, but both of them failed with "cannot depend on multiple scoped components".
EDIT: Apparently in order to get scoped providers, marking the components with the scope is not enough - you must specify the scope for the #Provides annotated methods too.
#Module
public class RepositoryModule {
#Provides
#Singleton
public PersonRepository personRepository() {
return new PersonRepositoryImpl();
}
#Provides
#Singleton
public ScheduleRepository schedulesRepository() {
return new SchedulesRepositoryImpl();
}
}
In the meantime, I ended up with this übercomponent.
#Singleton
#Component(modules = {
AppContextModule.class,
DbMapperModule.class,
DbTaskModule.class,
RealmModule.class,
RepositoryModule.class,
InteractorModule.class,
ServiceModule.class,
PresenterModule.class,
XmlPersisterModule.class
})
public interface ApplicationComponent
extends AppContextComponent, AppDataComponent, AppDomainComponent, AppUtilsComponent, AppPresentationComponent {
Where the xyzComponent classes are just interfaces to store the provision methods...
(Please note that this structure is an anti-pattern as described by Martin Fowler, and you should organize modules based on features / activities, and make them into subscoped components using component dependencies. Component dependencies are used to subscope your superscope components, and "inherit" dependency providers.)
I had same problems like you not while ago and ended using the same ubercomponent approach except I use #Subcomponents in order organize the things and not to have all modules listed in the ubercomponent (I call it "top" or "app's" component).
You may see an example here:
How to migrate missing inject from module with complete = false from Dagger 1 to Dagger 2
I have read many blogs but still i am not able to figure out #Module annotation functioning in dagger.
#Inject i got that it provides dependency injection at runtime. But what does #Module does.
since the object graph is also built on module.
For ex i.e i have this snippet of code from https://github.com/AndroidBootstrap/android-bootstrap.
#Module(
complete = false,
injects = {
BootstrapApplication.class,
BootstrapAuthenticatorActivity.class,
MainActivity.class,
BootstrapTimerActivity.class,
}
)
public class BootstrapModule {
}
so what does it basically does. since i am also trying to build one application using dagger as dependency injection for android.But since I am not able to get #Module concept clearly I am just stuck.
Can anyone please help me out with some basic example or concept. I think this will be helpful for all who is using dagger.
If you have a look to the docs for the annotation, a #Module annotated class defines a class that contributes to the dagger object graph. In the Spring framework for example, the equivalent would be the #Configuration anntotation. It defines a configuration point for your object graph, where you declare which objects you want to be available for injection and their scopes.
As a simple example, let's say we want a singleton object to be used by any Activity in the app. It has to be created in the module:
#dagger.Module(injects = {MyActivity.class})
public class Module {
#Provides
#Singleton
public MySinletonBean provideMySingleton() {
return new MySinletonBean();
}
}
This will create a MySingleton object which can be injected in MyActivity. This is a very basic example, but we can perform other actions in the graph there, like using dependencies in the constructors:
#dagger.Module(injects = {MyActivity.class})
public class Module {
private DependencyBean dependency = new DependencyBean();
#Provides
#Singleton
public MySinletonBean provideMySingleton() {
return new MySinletonBean(dependency);
}
#Provides
#Singleton
public MySinletonBean provideMyOtherSingleton() {
return new MyOtherSinletonBean(dependency);
}
}
Then, in MyActivity we need to access the graph for the application in the onCreate method:
#Inject
MySingletonBean singleton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
((MyApplication) getApplication()).getGraph().inject(this);
}
So, who does create the object graph here? The MyApplication class does it when your application starts (don't forger to add it in your androidManifest.xml):
public class MyApplication extends Application {
private ObjectGraph graph;
public ObjectGraph getGraph() {
return graph;
}
#Override
public void onCreate() {
super.onCreate();
graph = ObjectGraph.create(new Module(this));
graph.inject(this);
}
}
So the execution flow in a dagger app would be:
The android app starts and the MyApplication class builds the graph, parsing the #Module annotated classes and keeping an instance of it.
Then, the classes declared in the module can access its objects just injecting themselves in the object graph. Gradle then will evaluate their #Inject annotations and perform the dependency injections.
I guess Annotation Processing Tool requires that to generate code at the compile time.
This makes it Dagger can provide validation at compile time and not only at runtime.