Dagger小技巧之私有依赖

2020-05-12  本文已影响0人  珞泽珈群

前言

偶然间看到了这个关于Dagger小技巧的系列,很实用,也不复杂,在此我搬运转述一下。本文并非翻译,只是概述,想要更详细地了解,请查看原文:
Dagger Party Tricks: Private Dependencies

其它技巧:
Dagger小技巧之OkHttp延迟初始化
Dagger小技巧之Kotlin扩展函数

目的

利用Dagger的Qualifier来隐藏内部依赖。

问题

Dagger module:

@Module
object NetworkModule {
  @Provides fun client(): OkHttpClient {
    //...
  }
  
  @Provides fun retrofit(client: Lazy<OkHttpClient>): Retrofit {
    //...
  }
}

一般而言,以上模块的是为了提供Retrofit,OkHttpClient仅是Retrofit的内部实现细节,不应该在外部访问OkHttpClient,然而,事实并非如此:

@Module(includes = [NetworkModule::class])
object FeatureModule {
  @Provides
  fun networkAccessor(client: OkHttpClient): NetworkAccessor {
    // ಠ_ಠ
  }
}

我们依然可以在外部模块中访问OkHttpClient,这种访问可能是无意的,是对NetworkModule的错误使用,但是却是合法的,这实际上破坏了Dagger Module的封装,是应该避免的。

解决方案

Dagger有一种特性叫限定符(@Qualifier),默认情况下,Dagger以类型区分依赖注入的对象,如果一个类有两个或者更多的对象,那是会报错的:

@Module
object NetworkModule {
  @Provides fun provideName1(): String = “Lucy”
  
  //报错,同一类型String两个对象,无法区分
  @Provides fun provideName2(): String = “Lily”
}

这时候就需要用到@Qualifier@Qualifier实际上给Dagger提供了类之外额外的metadata(元数据),这样就可以区分相同类的两个对象了。实际上更准确的说法应该是,@Qualifier是类型签名(type signature)的一部分,提供@Qualifier实际上就是提供了一个新的类型,所以String@MyCustomQualifier String在Dagger看来是两种完全不同的类型。

扯了这么多@Qualifier,这和我们的问题有什么关系呢?当然有关,虽然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 可以使用内部类的方式:

@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限定的类也会成为私有的,在该Module之外都是无法访问的,这样就可以做到良好的封装。

私有限定符是避免内部依赖泄露的好方法。

上一篇下一篇

猜你喜欢

热点阅读