Hilt Components and Scopes in Android

ömer iyiöz
DigiGeek
Published in
4 min readFeb 5, 2021

Hi all ! This is my first medium post but not the last !

I will talk about the specific topic as stated in the title of this post.

The below is the components which can be used in Dagger Hilt ( https://dagger.dev/hilt/components.html ).

https://dagger.dev/hilt/components.html
https://dagger.dev/hilt/components

Below is a sample module we used for retrieving OkHttpClient instance.

I can write the same provider method as the following. The only difference of the below code is the usage of @Singleton annotation. Why do we need it or not ?

When we understand the difference, we will understand for what reasons the following keywords are used for :

  • @InstallIn annotation
  • Component annotations ( @SingletonComponent, @ActivityComponent, @FragmentComponent, … )
  • Scope annotations ( @Singleton, @ActivityScoped, @FragmentScoped, … )

Component

When we ask Dagger to give us an OkHttpClient instance, it will automatically create an OkHttpClient instance. What does determine the lifetime of OkHttpClient instance ? The answer is Component !

https://dagger.dev/hilt/components

Lets write the same code example again.

In this module class, we used the SingletonComponent. So we say that :

  • Hey Dagger, all the instances you will create in this module lives as long as the application lives.

When you need an application-scoped instance, use SingletonComponent.

Similarly, when you need per-activity or per-fragment scoped instances, use ActivityComponent or FragmentComponent respectively in your module. Or alternatively write your provider methods in the appropriate modules.

In the above code example, we teach the dagger how to create an OkHttpClient instance. Since we used the @InstallIn(SingletonComponent), this OkHttp instance will be application-wide.

I hope you understand why component is used. Now lets consider about scope annotations.

Scope annotations ( @Singleton, @ActivityScoped, @FragmentScoped, …)

Component determines the scope of the instance. But when we ask Hilt to give us an OkHttpClient in two different places, will it be singleton or not ? By default, it is not singleton. If you want an application wide singleton OkHttpClient instance, you should annotate your OkHttpClient provider method with @Singleton.

If you want an activity scoped instance, you use @ActivityComponent, but this instance is not singleton in activity scope by default. If you want an activity scoped singleton instance, you should use @ActivityComponent and @ActivityScoped .

Below is an example usage of FragmentComponent and @FragmentScoped annotation from https://dagger.dev/hilt/components.html.

https://dagger.dev/hilt/components

Note: When scoping a binding within an @InstallIn module, the scope on the binding must match the scope of the component. For example,

  • a binding within an @InstallIn(ActivityComponent.class), module can only be scoped with @ActivityScope.
  • a binding within an @InstallIn(FragmentComponent.class) module can only be scoped with @FragmentScope.
  • a binding within an @InstallIn(SingletonComponent.class) module can only be scoped with @SingletonScope.

Scoping is expensive. Use it if you really need it !!

Scoping a binding has a cost on both the generated code size and its runtime performance so use scoping sparingly. The general rule for determining if a binding should be scoped is to only scope the binding if it’s required for the correctness of the code. If you think a binding should be scoped for purely performance reasons, first verify that the performance is an issue, and if it is consider using @Reusable instead of a component scope.

Scoped vs unscoped bindings

By default, all bindings in Dagger are “unscoped”. This means that each time the binding is requested, Dagger will create a new instance of the binding.

In the following examples, we teach the dagger how to create UserManager instance. Be aware that we do not use scope annotation below. Thus, when we ask dagger to inject a UserManager instance each time, the Dagger will create a new instance.

If you want an application wide singleton UserManager instance, you should use @Singleton annotation.

If you want an activity-scoped or fragment-scoped singleton UserManager instance, you should use @ActivityScoped or @FragmentScoped annotation respectively.

This is the end of this post. I hope you understand the concept.

If you need this post is helpful, please clap for support.

If you think that this post has missing parts or can be improved, you can comment the post, or you can connect with me on LinkedIn and we can talk about it.

Happy coding !

https://dagger.dev/hilt/components

--

--