Dagger2是由Google维护的Android依赖注入框架,依赖注入 (DI) 是一种在编程中广泛使用的技术,非常适合 Android 开发。

添加Dagger2

app/build.prop参考如下配置添加kapt插件和dagger依赖

// app/build.prop
plugins {
    //...
    id 'kotlin-android'
    id 'kotlin-kapt'
    //...
}
​
dependencies {
    //...
    implementation "com.google.dagger:dagger:2.x"
    kapt "com.google.dagger:dagger-compiler:2.x"
    //...  
}

常用注解

  • @Inject

    @Inject能够修饰方法、字段、构造方法,Dagger可通过此知道类的构建方式以及依赖项

    //当@Inject修饰构造函数时,它告诉 Dagger 如何提供该类的实例
    open class Person @Inject constructor(private val context: Context) {
          fun showWho() {
              
          }
    }
    ​
    class MainActivity : AppCompatActivity() {
        //当@Inject修饰字段时,Dagger需要使用该类型的实例填充字段
        //@Inject不能注解private成员
        //@Inject
        //lateinit var mPerson: Person
    }
  • @Component

    @Component用来修饰接口或者抽象类,Dagger需要它来创建依赖关系图

    @Component
    interface PersonComponent {
        //通过Inject方法,告诉Dagger请求MainActivity的注入
        fun inject(activity: MainActivity)
    }
  • @Module@Binds

    @Module用来注释类,告诉Dagger如何提供类的实例

    @Binds用来告诉Dagger需要使用哪个接口实现

    @Module
    abstract class PersonalModule {
    ​
        @Binds
        abstract fun getWoman(womanPerson: WomanPerson): Person
    ​
        @Binds
        abstract fun getMan(manPerson: ManPerson): Person
    ​
    }
    ​
    class ManPerson @Inject constructor(private val context: Context) : Person(context)
    class WomanPerson @Inject constructor(private val context: Context) : Person(context)

    然后我们把PersonModule关联到PersonComponent

    @Component(modules = [PersonModule::class])
    interface PersonComponent {
        fun inject(activity: MainActivity)
    }

    此时PersomComponent就知道PersonModule所包含的信息了

  • @BindsInstance

    有时候需要提供Context来构建类,但是Context不能被注解到,那么@BindsInstance就可以告诉Dagger在需要时提供Context实例

    @Component(modules = [PersonModule::class])
    interface PersonComponent {
        fun inject(activity: MainActivity)
        
        @Component.Factory
        interface Factroy{
            fun provideContext(@BindsInstance context: Context): PersonComponent       
        }
    }

    通过Build Rebuild Project构建后,Dagger就可以生成DaggerPersonComponent了,回到MainAcitivty进行依赖注入

    class MainActivity : AppCompatActivity() {
    ​
        @Inject
        lateinit var man:ManPerson
    ​
        @Inject
        lateinit var womanPerson: WomanPerson
    ​
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            //一步完成全部注入
            DaggerPersonComponent.factory().provideContext(this).inject(this)
            //无需生成实例直接使用
            man.showWho()
            womanPerson.showWho()
        }
    }

    通常情况下,Dagger应该在应用运行是就在内存中,会将DaggerPersonComponent.factory().provideContext(this)放在Application中,然后在需要的时候调用之

    class MainApplication : Application() {
    ​
      val personComponent: PersonComponent by lazy {
          DaggerPersonComponent.factory().provideContext(this)
      }
    }
    ​
    class MainActivity : AppCompatActivity() {
    ​
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)
    ​
          (application as MainApplication).personComponent.inject(this)
      }
    }
  • @Singleton单例模式

    使用单例模式需要在对应的Component接口和待实例化的类前增加@Singleton标注,即可对象的单例实例化

    @Singleton
    interface PersonComponent {/*...*/}
    ​
    @Singleton
    class ManPerson @Inject constructor(private val context: Context) : Person(context)
  • @Subcomponent 子组件

    子组件是继承自父组件Dagger图的组件,父组件中提供的所有对象也会在子组件中提供。这样,来自子组件的对象可以依赖于父组件提供的对象。

    子组件的写法与父组件基本一致,只是需要将@Component换成@SubComponent,在父组件中,需要指定子组件

    @Component(modules = [PersonalModule::class, PersonSubModule::class])
    interface PersonComponent {
    //...
      fun registrationComponent(): SubComponent.Factory
    //...  
    }
    ​
    @Subcomponent
    interface SubComponent {
      //...
      @Subcomponent.Factory
      interface Factory {
          fun create(): SubComponent
      }
      //...
    }
    ​
    @Module(subcomponents = [SubComponent::class])
    abstract class PersonSubModule {
    ​
      @Binds
      abstract fun getPerson(person: OtherPerson):Person
    }

    Subcomponent必须由Component调用方法获取

    (application as MainApplication).personComponent.registrationComponent().create()
  • @Provides 自定义实例化的方式覆盖默认实例化方式

    @Module
    abstract class PersonalModule {
    ​
      @Binds
      abstract fun getWoman(womanPerson: WomanPerson): Person
    ​
      @Provides
      fun provideWoman(context: Context):WomanPerson{
          return WomanPerson(context)
      }
    }


本站由 TrillionByte 使用 Stellar 创建。