Android — Clean architecture with Dynamic-features and Hilt/Dagger2 (Pt.3)

Pedro Okawa
3 min readMar 5, 2021
Barcelona — Spain (2019)

Introduction

As you noticed by the title, this is the third part of the series of articles explaining and describing my process of creating an application using dynamic features with Hilt/Dagger. You may find the previous posts here:

Hilt / Dagger

The proper setup to use Hilt in your application is well-described on Google’s webpage, but I’ll quickly show an example based on the code I implemented.

In order to use Hilt, we must annotate our Application class with @HiltAndroidApp.

App

If we are going to manage dependency injection on our app module, we can still use Hilt by adding the @AndroidEntryPoint on one of the following Android components:

  • Application (by using @HiltAndroidApp)
  • ViewModel (by using @HiltViewModel)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

To exemplify, we are going to inject an instance of a “ColorProvider” inside our view model.

ColorProvider

First, we need to annotate the activity and fragment holding this fragment with the @AndroidEntryPoint

TutorialActivity
TutorialFragment

With that done, we are now able to inject our “ColorProvider” inside our view model by using a binding injection on our constructor

TutorialViewModel

Great, that’s enough to have our dependency injection working on our app module, but what about our dynamic features?

Dagger2

Well, Hilt is not supported yet on dynamic features, and the workaround is to use Dagger2 instead, and now here comes the trick. Hilt provides an annotation to help with that called @EntryPoint, so we must declare an interface in our app module annotated with this and provide the function signatures of the dependencies that will be used by our dynamic features. In our example, the only dependency that is being used by the other modules is Retrofit.

DaggerDependencies

The dependencies declared must be installed in a defined scope by using the @InstallIn annotation, which in our case is defined into SingletonComponent

Feature module

Now, in our feature module, we must create a component that depends on the DaggerDependencies interface we created and also add all the needed Dagger modules.

PoolsComponent

In order to make our dependencies work, we must define an inject function that receives as a parameter the target class to inject the dependencies, which will be in our case our fragment.

For those who already worked with Dagger and multi-modules, this is not new, the only difference is the appDependencies function defined inside the Builder, which is the key to connect our dependencies.

Right after declaring the component and rebuild your project, you will be able to locate the generated Dagger component that will be named “DaggerPoolsComponent”

PoolsFragmentExtension

Do you remember the appDependencies function we defined in our component? It is time for it to shine. We must call this function and pass the EntryPoint we defined using the “EntryPointAccessors”.

Note: I defined the inject function using extension functions to reduce the amount of code inside my fragment, but it could be defined inside the fragment without any problems.

PoolsFragment

Now the only thing we must do to fulfill our mission is to call the inject function, and according to Google’s documentation, we must do it inside the onAttach function.

When using activities, inject Dagger in the activity’s onCreate() method before calling super.onCreate() to avoid issues with fragment restoration. During the restore phase in super.onCreate(), an activity attaches fragments that might want to access activity bindings.

When using fragments, inject Dagger in the fragment’s onAttach() method. In this case, it can be done before or after calling super.onAttach().

We now have finished the setup to use dynamic-features along with Hilt/Dagger.

Congratulations and thanks for accompanying me on that journey!!! 🎉

Any thoughts ideas or suggestions, please add some comments.

--

--