Easy Android Dagger 2 Architecture
Yeah! Are you an Android geek? Are you a fan of the square? Yep, I’m. Here we are going to implement dagger a butter in Android.
Before getting into a deep pinch, let’s take a look at what dagger 2 does for Android!
Dagger 2:
Dagger is a fully static, compile-time dependency injection framework for Android which helps developers to write optimized code in a way to create Singleton
instances throughout the application using @Provides
and @Inject
annotations. For better understanding, let us segregate the dagger 2 setup into the following steps:
STEP 1: Add the following gradle dependencies into the build.gradle (Module: app)
compile 'com.google.dagger:dagger:2.6'
annotationProcessor 'com.google.dagger:dagger-compiler:2.6'
STEP 2: Here we come! It’s good news for Android folks! Now say ‘No’ to com.neenbedankt.android-apt
plugin support in dependencies for Android Studio gradle build version 2.3.0 and above, since annotationProcessor
solves this purpose.
STEP 3: Create a Dagger Module class with @Module annotation with your desired name. I am gonna name it DaggerModule.java
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.takeoffandroid.androidcleandagger2architecture.modules.Dag gerPresenter;
import com.takeoffandroid.androidcleandagger2architecture.modules.DaggerPresenterImpl;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class DaggerModule {
private Context context;
public DaggerModule(Application app) {
this.context = app;
}
@Provides
Context providesContext() {
return context;
}
@Provides
@Named("DaggerModule.UserMobile")
String providesSharedPrefValue() {
return "9789010929";
}
@Provides
@Singleton
SharedPreferences providesSharedPreferences(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context);
}
@Provides
@Singleton
DaggerPresenter providesDaggerPresenter(@Named("DaggerModule.UserMobile") String userMobile, SharedPreferences sharedPreferences){
return new DaggerPresenterImpl(userMobile,sharedPreferences);
}
}
Dagger 2 Annotations:
@Module
— This Annotation is used on top of the class to mark the particular class as a Module component. Here I have created DaggerModule.java
and tagging this as a module by using @Module annotation.
@Singleton
— It creates one instance throughout the application. Yeah! It’s a common phenomenon.
@Provides
— It defines methods that provide dependencies.
You can see the below code snippets where I have created @Provides
method for Context and SharedPreferences.
@Provides
@Singleton
SharedPreferences providesSharedPreferences(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context);
}
@Provides
Context providesContext() {
return context;
}
How @Provides
Annotation Works?
It binds the Actual name (Context, SharedPreferences, Retrofit, OkHttpClient, etc.,)with the user-defined method name.
For Example:
providesSharedPreferences()
— provides(user defined method name. It can be provide, provides, etc. But lets fix it to one common global standard provides)
provides + SharedPreferences which in turn provides SharedPreferences access to Activity, Fragment or wherever needed using @Inject
annotation. In this tutorial, we are passing the SharedPreferences instance to presenter implementation.
2. providesContext()
— provides + Context which in turn provides Context access.
@Named
— This annotation is used to tag a particular provides a method of any return type like String, int, Objects, etc. This annotation type accepts String as a key and it can be accessed in any provided method through a unique key.
@Provides
@Named("DaggerModule.UserMobile")
String providesUserMobile() {
return "9789010929";
}
Where “DaggerModule.UserMobile” is the key for the method type.
We’re gonna pass this @Named(“DaggerModule.UserMobile”)
into DaggerPresenterImpl
class.
@Provides
@Singleton
DaggerPresenter providesDaggerPresenter(@Named ("DaggerModule.UserMobile") String userMobile, SharedPreferences sharedPreferences){
return new DaggerPresenterImpl(userMobile,sharedPreferences);
}
Yeah! We’re almost done. Now couple this DaggerModule into Component (DaggerComponent.java)using @Component annotation.
STEP 4: Create an interface for a Component. I am naming it as DaggerComponent in this tutorial.
@Singleton
@Component(modules = {DaggerModule.class})
public interface DaggerComponent {
void inject(MainActivity mainActivity);
}
STEP 5: Last but not least! Now it’s time to bind Dagger 2 into the Application class.
package com.takeoffandroid.androidcleandagger2architecture;
import android.app.Application;
import dagger.Module;
@Module
public class DaggerApplication extends Application {
private DaggerComponent daggerComponent;
@Override
public void onCreate() {
super.onCreate();
daggerComponent = createDaggerComponent();
}
public DaggerComponent getDaggerComponent() {
return daggerComponent == null ? createDaggerComponent() : daggerComponent;
}
private DaggerComponent createDaggerComponent() {
return DaggerDaggerComponent.builder().daggerModule(new DaggerModule(this)).build();
}
public void clearComponent() {
daggerComponent = null;
}
}
Now let’s focus on the key factors where there is no proper documentation to explain this logic behind Dagger 2 implementation.
DaggerDaggerComponent.builder().daggerModule(new DaggerModule(this)).build();
The above code snippet is used to bind Dagger 2 into application. But it is bit messy and hard to resolve issues if you are new to Dagger 2. Let’s split the above snippet into parts as follows
- DaggerDaggerComponent .builder()— Dagger (Common Notation to bind)+ DaggerComponent (Your Dagger Component class)
For Example:
- If your Component name is AppComponent, then it should be DaggerAppComponent
2. daggerModule(new DaggerModule(this)) — Convert your Dagger Module class into camel case characters.
For Example:
In my case, DaggerModule.java is my dagger module class, hence it is daggerModule
If your module name is AppModule.java, then it should be appModule
STEP 6: Let’s inject Dagger 2 in Activity.
((DaggerApplication) getApplication()).getDaggerComponent().inject(MainActivity.this);
Note: It is mandatory to inject Dagger 2 from Component in your Activity or Fragment to make use of Dagger 2 annotations by creating inject method inside your component class with Context like as follows
package com.takeoffandroid.androidcleandagger2architecture;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {DaggerModule.class})
public interface DaggerComponent {
void inject(MainActivity mainActivity);
}
LAST STEP: In the Activity or Fragment, use @Inject
method to get the object of the @Provides annotation created in the module. In my case, I am gonna inject DaggerPresenter class to save and retrieve user's mobile number from SharedPreferences
Happy Coding!
Subscribe to my newsletter
Read articles from Chandrasekar Kuppusamy directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by