Migrating From Dagger to Hilt

Learn about Hilt and its API. Discover how Hilt facilitates working with Dagger by migrating the code of an existing app from Dagger to Hilt. By Massimo Carli.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Using @AndroidEntryPoint With Fragments

Hilt supports @AndroidEntryPoint for Fragments as well. Open ui/list/NewsListFragment.kt and look at its relevant code:

class NewsListFragment : Fragment(), NewsListView {

  @Inject
  lateinit var newsListPresenter: NewsListPresenter // 1
  // ...
  override fun onAttach(context: Context) {
    (context as FeatureComponentProvider).get().inject(this) // 2
    super.onAttach(context)
    Log.i(TAG, "In NewsListFragment using NewsListPresenter $newsListPresenter")
  }
  // ...
}

In this code, you:

  1. Use @Inject to get a reference to NewsListPresenter.
  2. Get the actual injection, invoking inject() on the FeatureComponent you get from the container Activity. In this case, it’s MainActivity.

The second point is what makes NewsListFragment an injection target. That’s the code Hilt writes for you when you use @AndroidEntryPoint. You just need to update NewsListFragment to the following, keeping the rest of the code unchanged:

@AndroidEntryPoint
class NewsListFragment : Fragment(), NewsListView {

  @Inject
  lateinit var newsListPresenter: NewsListPresenter // 1
  // ...
}

In this code, you:

  1. Annotated NewsListFragment with @AndroidEntryPoint, telling Hilt that this is an entry point and, therefore, a target for injection.
  2. Removed onAttach(), which used to contain the code for the injection that Hilt generates for you now.

Next, open ui/detail/NewsDetailFragment.kt and apply the same changes, removing onAttach() and adding the @AndroidEntryPoint annotation. You’ll get something like the following:

@AndroidEntryPoint
class NewsDetailFragment : Fragment(), NewsDetailView {

  @Inject
  lateinit var newsDetailPresenter: NewsDetailPresenter
  // ...
}

Cool! You were able to remove quite a bit of code because Hilt now creates the @Component for you. But there’s one last step to do.

What About @Scopes?

So far, you learned that for each predefined @Component, Hilt also provides a predefined @Scope. For the objects you’re injecting into RWNEws, you created the custom @FeatureScope scope, which you can now remove.

To do this, open presenter/impl/NewsListPresenterImpl.kt and update it to replace @FeatureScope with @FragmentScoped:

@FragmentScoped // HERE
class NewsListPresenterImpl @Inject constructor(
    private val newsRepository: NewsRepository
) : BasePresenter<NewsListModel, NewsListView>(),
    NewsListPresenter {
  // ...
}

Do the same in presenter/impl/NewsDetailPresenterImpl.kt. You’ll end up with the following code:

@FragmentScoped // HERE
class NewsDetailPresenterImpl @Inject constructor(
    private val newsRepository: NewsRepository,
    private val newsStats: @JvmSuppressWildcards(true) Set<NewsStats>
) : BasePresenter<NewsModel, NewsDetailView>(),
    NewsDetailPresenter {
  // ...
}

Now, you can finally build and run without a compilation error. You’ll get the same experience as you had with the original app:

RWNEws App

Brilliant! Those were quite a few changes, but now, finally, you’ve fully migrated your app from Dagger to Hilt. :]

IDE Support for Hilt

When you work on a big project, you might use classes with many dependencies — which means you might struggle to understand where they come from. Starting with Android Studio 4.1, the IDE supports navigating the code generated with Hilt.

To try this, open ui/list/NewsListFragment.kt. You’ll see a new icon on the left of the dependency, like this:

Android Studio icon for a provided dependency

This is the icon that Android Studio uses to represent a provided dependency. Select the icon and you’ll navigate directly to the point in the code that provides the injected object. In this example, you’ll go to FeatureModule, and more specifically, the cursor will appear next to provideNewsListPresenter.

Android Studio icon for a dependency definition

In the screenshot above, you see the second type of icon that allows you to navigate to the point in the code where the correspondent definition is injected. Select the icon next to line 18 in the example and you’ll go back to NewsListFragment.

Now, select the icon beside the name of the module — the one marked with a circle — and Android Studio will display all the locations where the module is used:

Android Studio showing module usage

You’ve now covered the fundamentals of Hilt and its APIs! :]

Where to Go From Here?

Download the final version of this project by using the Download Materials button at the top or bottom of this tutorial.

Great job completing the tutorial! You learned what Hilt is and how you can migrate your app to it from Dagger. You learned what the standard Hilt components and scopes are and how they simplify the code in your app.

What you saw here is just the beginning — Hilt can do much more for you. The next step is to learn how it can simplify testing your app. Stay tuned for coming tutorials on this topic!

To learn more about Hilt, check out the video course Dependency Injection with Hilt: Fundamentals.

If you have any comments or questions, feel free to join the discussion below.