Dagger小技巧之私有依賴

前言

偶然間看到了這個(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)部依賴泄露的好方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容