In my last tutorial, we had functioned with Dagger2 in android application development. Dagger 2 is an awesome dependency injection library which provides the alternative way of Object instantiation. I already explained what is Dagger2 and why we are using this in android application development and what are the benefits of using this? Here is the detail of Dagger2 dependency injection with Android.
In this tutorial, we will learn to integrate the new Dagger2 with android architecture component. Implementation of Dagger2 with android architecture is slite changed. It provides much more fanciable and easy to provide the instance. The very first thing we need to add the relevant dependencies in your android build.gradle file.
ext { daggerVersion = '2.11' dagger = "com.google.dagger:dagger:$daggerVersion" daggerCompiler = "com.google.dagger:dagger-compiler:$daggerVersion" daggerAndroid = "com.google.dagger:dagger-android:$daggerVersion" }
Android architecture design is based on the view model. So Every module will inject with view model by Dagger2. Now in the next step, we need to get the activity injector in the main application (An Application that injects its members and can be used to inject Activities, Fragments, Services, BroadcastReceivers and ContentProviders attached to it.).
We have already checked with the old way instantiation of an object, here is an example of a sample.
private void injectDependency() { ApplicationComponent applicationComponent = ((MainApplication) getActivity().getApplication()).getApplicationComponent(); ArticleComponent articleComponent = DaggerArticleComponent.builder() .applicationComponent(applicationComponent) .articleModule(new ArticleModule()) .build(); articleComponent.inject(this); }
Ok, let’s implement new Dagger2 injection. We need to initialize the Dagger2 component in Main Application by implementing new HasActivityInjector (Provides an AndroidInjector
of Activity
s.)
public class MainApplication extends Application implements HasActivityInjector{ @Inject DispatchingAndroidInjector<Activity> activityDispatchingAndroidInjector; @Override public void onCreate() { super.onCreate(); initializeComponent(); } @Override public AndroidInjector<Activity> activityInjector() { return activityDispatchingAndroidInjector; } private void initializeComponent() { DaggerAppComponent.builder() .application(this) .build() .inject(this); } }
Dagger2 introduced some of the new component builders. Let’s see in detail.
@ContributesAndroidInjector (module)
and @ContributesAndroidInjector
If an activity builder module containing any Fragment or view then we can provide the specific Fragment module to contribute for the android injector and if not then simply annotated with @ContributesAndroidInjector. To mapping all activity and pass it to Dagger2 we will create the ActivityBuilderModule.
@Module public abstract class ActivityBuilderModule { @ContributesAndroidInjector(modules = FragmentBuilderModule.class) abstract MainActivity mainActivity(); @ContributesAndroidInjector abstract MovieDetailActivity movieDetailActivity(); }
Dagger know our activities in compile time. In our app, we have Main and Detail activity. So we map both activities here.
@Component
and @Component.Builder
A component will provide injected instances by using modules. Component.Builder used for instantiation of a component. We can create the interface of the builder and annotate with @Component.Builder and build by @BindInstance.
@Singleton @Component(modules = {AppModule.class, AndroidInjectionModule.class, ActivityBuilderModule.class}) public interface AppComponent { @Component.Builder interface Builder { @BindsInstance Builder application(Application application); AppComponent build(); } void inject(MainApplication aaApp); }
AppModule: App Module provides retrofit, okhttp, persistence DB, shared pref etc here. So our dagger graph will understand that.
@Module(includes = ViewModelModule.class) public class AppModule { @Provides @Singleton OkHttpClient provideOkHttpClient() { OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder(); okHttpClient.connectTimeout(Constant.TIMEOUT_IN_SEC, TimeUnit.SECONDS); okHttpClient.readTimeout(Constant.TIMEOUT_IN_SEC, TimeUnit.SECONDS); okHttpClient.addInterceptor(new RequestInterceptor()); return okHttpClient.build(); } @Provides @Singleton ApiServices provideRetrofit(OkHttpClient okHttpClient) { Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constant.ENDPOINT) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build(); return retrofit.create(ApiServices.class); } @Provides @Singleton MovieDatabase provideMovieDatabase(Application application) { return Room.databaseBuilder(application, MovieDatabase.class, "aa.db").build(); } @Provides @Singleton MovieDao provideMovieDao(MovieDatabase movieDatabase) { return movieDatabase.movieDao(); } }
ViewModelModule: VewModelModule has all the module information about the each ViewModel and injects those when we required.
@Module public abstract class ViewModelModule { @Binds @IntoMap @ViewModelKey(MovieListViewModel.class) abstract ViewModel bindsMovieListViewModel(MovieListViewModel movieListViewModel); @Binds @IntoMap @ViewModelKey(MovieDetailViewModel.class) abstract ViewModel bindsMovieDetailViewModel(MovieDetailViewModel movieDetailViewModel); @Binds abstract ViewModelProvider.Factory bindsViewModelFactory(MovieViewModelFactory movieViewModelFactory); }
We can inject MovieListViewModel by annotated @Inject.
@Inject MovieListViewModel movieListViewModel;
Now in the last activity and Fragment should know that how Dagger injected. So we need to tell by AndroidInjection.inject() method in onCreate() of Activity or onAttach() of Fragment.
public class MainActivity extends AppCompatActivity implements HasSupportFragmentInjector{ @Inject DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector; @Override protected void onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); } @Override public AndroidInjector<Fragment> supportFragmentInjector() { return fragmentDispatchingAndroidInjector; } }
Wrapping up: Ok, You have done so for. The conclusion is that It does not matter how many class files need to create the most important that our code will be in well structured and we do not worry about any refactor or changes in code in future. I used the article reference here.
Here is the Github link for an Android Architecture Sample project.
Please do subscribe email to get all newsletters of this blog and if you feel that this post will help you to better understand then do not forget to subscribe, share and comment below. Ok, then I will see you in my next tutorial till then enjoy your life and happy coding 🙂
I am a very enthusiastic Android developer to build solid Android apps. I have a keen interest in developing for Android and have published apps to the Google Play Store. I always open to learning new technologies. For any help drop us a line anytime at contact@mobologicplus.com
Nice tutorial and sample app, very useful Thanks
Thanks Jaime
nice tutorial,
i have question, how you implemen Broadcastreciver with Dagger 2?
Hi Heri Setiawan, Thanks for the comment. In simple word, it is not if the receiver added in manifest because it will be created before the Android Application class has started and more than likely you will not have an object graph created before this point. Reference https://plus.google.com/+DavidCarver_kingargyle/posts/MzMWFvBMCn5