前言
偶然間看到了這個(gè)關(guān)于Dagger小技巧的系列,很實(shí)用,也不復(fù)雜,在此我搬運(yùn)轉(zhuǎn)述一下。本文并非翻譯,只是概述,想要更詳細(xì)地了解,請查看原文:
Dagger Party Tricks: Private Dependencies
其它技巧:
Dagger小技巧之OkHttp延遲初始化
Dagger小技巧之Kotlin擴(kuò)展函數(shù)
目的
利用Dagger的Qualifier來隱藏內(nèi)部依賴。
問題
Dagger module:
@Module
object NetworkModule {
@Provides fun client(): OkHttpClient {
//...
}
@Provides fun retrofit(client: Lazy<OkHttpClient>): Retrofit {
//...
}
}
一般而言,以上模塊的是為了提供Retrofit,OkHttpClient僅是Retrofit的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),不應(yīng)該在外部訪問OkHttpClient,然而,事實(shí)并非如此:
@Module(includes = [NetworkModule::class])
object FeatureModule {
@Provides
fun networkAccessor(client: OkHttpClient): NetworkAccessor {
// ?_?
}
}
我們依然可以在外部模塊中訪問OkHttpClient,這種訪問可能是無意的,是對(duì)NetworkModule的錯(cuò)誤使用,但是卻是合法的,這實(shí)際上破壞了Dagger Module的封裝,是應(yīng)該避免的。
解決方案
Dagger有一種特性叫限定符(@Qualifier),默認(rèn)情況下,Dagger以類型區(qū)分依賴注入的對(duì)象,如果一個(gè)類有兩個(gè)或者更多的對(duì)象,那是會(huì)報(bào)錯(cuò)的:
@Module
object NetworkModule {
@Provides fun provideName1(): String = “Lucy”
//報(bào)錯(cuò),同一類型String兩個(gè)對(duì)象,無法區(qū)分
@Provides fun provideName2(): String = “Lily”
}
這時(shí)候就需要用到@Qualifier,@Qualifier實(shí)際上給Dagger提供了類之外額外的metadata(元數(shù)據(jù)),這樣就可以區(qū)分相同類的兩個(gè)對(duì)象了。實(shí)際上更準(zhǔn)確的說法應(yīng)該是,@Qualifier是類型簽名(type signature)的一部分,提供@Qualifier實(shí)際上就是提供了一個(gè)新的類型,所以String和@MyCustomQualifier String在Dagger看來是兩種完全不同的類型。
扯了這么多@Qualifier,這和我們的問題有什么關(guān)系呢?當(dāng)然有關(guān),雖然Dagger Module是公有的,但是我們可以通過私有的Qualifier,來限制Module外的訪問:
@Retention(BINARY)
@Qualifier
private annotation class InternalApi
@Module
object NetworkModule {
@Provides
@InternalApi
fun provideClient(): OkHttpClient {
//...
}
@Provides
fun provideRetrofit(
@InternalApi client: Lazy<OkHttpClient>
): Retrofit {
//...
}
}
Java 可以使用內(nèi)部類的方式:
@Module
public class NetworkModule {
@Retention(CLASS)
@Qualifier
private @interface InternalApi {}
@Provides
@InternalApi
static OkHttpClient provideClient() {
//...
}
@Provides
static Retrofit provideRetrofit(
@InternalApi Lazy<OkHttpClient> client
) {
//...
}
}
由于InternalApi是私有的,所以InternalApi限定的類也會(huì)成為私有的,在該Module之外都是無法訪問的,這樣就可以做到良好的封裝。
私有限定符是避免內(nèi)部依賴泄露的好方法。