美文网首页
Dagger小技巧之私有依赖

Dagger小技巧之私有依赖

作者: 珞泽珈群 | 来源:发表于2020-05-12 15:57 被阅读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之外都是无法访问的,这样就可以做到良好的封装。

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

    相关文章

      网友评论

          本文标题:Dagger小技巧之私有依赖

          本文链接:https://www.haomeiwen.com/subject/jngbnhtx.html