Hilt InstallIn ScopeComponent vs Scope Annotation

這兩個 Scope Annotation 到底有什麼不同?

Ray Yuan Liou
5 min readApr 28, 2022
到底是哪一個?
到底是哪一個?

InstallIn(ScopeComponent)

代表這個 Module 從什麼階段被產生,就像我們過去如果手動做 Singleton dependency,我們會把這個 Class 和這個 App 的 Application 生命週期綁在一起。

這邊的 @InstallIn() 代表 Hold 住這些 Dependency Reference 的 Class 什麼時候被產生、被消滅。(並不含 Dependency 本身,這些 Class 總需要有人 Hold 著他吧?) 例如,@InstallIn(SingletonComponent::class) 代表這個 Module Class 在 Application 產生時就會被產生,Application Destroy 後會被回收。

再舉個例子:@InstallIn(ActivityScope::class) 這個 Module class 在被 Inject 到 Activity 後,會跟著 Activity onCreate, onDestory 而被產生,被回收。

不過,Module 裡頭定義的 Dependency,需要也定義他的 Scope,才有辦法跟著 Module 一起產生一起被回收。否則,這個 Dependency 就是 One Shot 的,只在 Inject 時產生,這個 Android Context Object 死亡後也跟著被回收。

在這裏參照相對應的[生命週期](Hilt Components (dagger.dev))

Scope Annotation

- Put on constructor or Provides
- scoped and non-scoped bindings
- this scope annotation must comes with in constructor. (or Provides with a scope.)

我們一般注入 我們可以控制的 的 Object 時(一般來說,是可以摸到他的 Constructor 的),會在這個 Class 的 Constructor 加上 @Inject Annotation,告訴 Hilt 這個 Class 是可以被提供給其他人的

Constructor injection

這個 MyCustomManager就是一個 unscope binding dependency。代表他是 One Shot,每次 Inject 每次建立一個新的,並且在附著的 Android Context Object 死亡後,也跟著被回收。

如果需要加上 Scope,我們可以在這類型的 Class 之中,加入 Scope Annotation,像是:

Constructor injection with scope

代表這個 MyCustomManager 是一個 Singleton 物件。 只要標上 Scope 的 Dependency,就是一個 scoped binding dependency。 也可以將他標示成 @ActivityScope 或是 @FragmentScope 等,如此一來,他的生命週期將會跟著這些 Android Context Object 一起出生、死去。

第三方

通常是第三方 Library,或是 Constructor 是我們不能控制的 Class。這時就需要寫一個 Hilt Module,讓 Hilt 認得這個 Dependency。

例如 Retrofit,沒辦法去改寫他的 Constructor,讓他多一個 @Inject Annotation,所以我們需要手動寫一個 Module 讓 Hilt 認得他。

Creation of third party app

這裡可以看到這個 NetworkModule,是 SingletoneComponent,在 Application onCreate() 時就會被產生。

不過,Retrofit 是一個 unscope binding dependency,因為這個 provideRetorfit() 方法並不包含任何的 Scope Annotation。這也代表,這個 Retrofit object 在每次 Hilt 提供給任何需要的 Class 時,都會是一個 全新的 Class。

如果我們需要將 Retrofit 變成一個 Singleton Object,則加上對應的 Scope Annotation 即可。

Singleton Retrofit instance

如此一來,每一次 Hilt 提供 Retrofit 給需要的 Class 時,就會取得同一個。

InstallIn(Components) vs Scope

需要注意的是,當已經指定 @InstallIn(ScopeComponent),這個 Module 包含的 Dependency 想要指定成 scoped binding dependency,就只能使用與該 ScopeComponent 相對應的 Scope。 例如,一個被設定成 @InstallIn(ActivityComponent::class) 的 Module,該 Module 的 scoped binding dependency 需要被設定為 @ActivityScope

參照自官方文件:

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 @ActivityScoped.

Scopes in Binds

與 Provides 相同,在 @Binds 上方加上相對應的 Scope Annotation 即可。

Scope in Binds

延伸閱讀

Hilt Components

--

--