Android使用Dagger注入的方式初始化对象的简单使用

发布时间 2023-07-18 15:12:59作者: 小寻

一. Dagger简介

Dagger 2 是 Google 开源的一款依靠注入结构,它的前身是 square 的 Dagger 1,Dagger 2 在 Android 中有着较为广泛的运用。

Dagger 2 根据 Java 注解,采用 annotationProcessor(注解处理器) 在项目编译时动态生成依靠注入需求的 Java 代码,然后咱们在合适的位置手动完结终究的依靠注入,而不是 Dagger 1 中根据反射的解决方案,所以在性能上是有保障的。

Android官方dagger介绍:https://developer.android.google.cn/training/dependency-injection/dagger-basics?hl=zh-cn

二. Dagger的依赖

// kapt is for implement annotation
apply plugin: 'kotlin-kapt'

// implementation some depend for dagger
implementation "com.google.dagger:dagger:2.21"
implementation "com.google.dagger:dagger-android-support:2.21"
kapt "com.google.dagger-compiler:2.21"
kapt "com.google.dagger-android-processor:2.21"

二. Dagger的配置

1. 初始化对象配置

1.1 使用@Inject注解初始化对象

注意:使用@Inject注解初始化对象时,构造函数所需的参数也必须已经使用dagger初始化,否则编译时会报错:com.record.sample.**** cannot be provided without an @Inject constructor or an @Provides-annotated method

1 @Singleton
2 class RecordContractImple @Inject constructor(): RecordContract{
3   // empty body
4 }
1 @Singleton
2 class PicruteAdapter@Inject constructor(
3     context: Context
4 ): RecyclerView.Adapter<>{
5   // empty body
6 }

1.2 使用provide类初始化

@Module
class RecordModule {
  @Provides
  @Singleton   fun provideRecordAdapter(
    context: Context
  ): RecordAdapter
= RecordAdapter(context)

  @Provides
  @Singleton
  fun provideRecordContract(
    recordContractImpl: RecordContractImpl  
  ): RecordContract = recordContractImpl }

2. 绑定页面与使用Dagger初始化的对象

设置哪些页面可以使用@Inject方式获取Dagger初始化的对象。(ContributesAndroidInjector参数设置待确认

@Module
interface BindRecordModule {
  @ContributesAndroidInjector
  fun bindMainActivity(): MainActivity

  @ContributesAndroidInjector
  fun bindHomeFragment(): HomeFragment
}

3. 定义Component配置moudle

将1和2中的配置配置到Dagger中以生效

@Singleton
@Component(
  modules = [
    // default module, must add
    AndroidSupportInjectionModule::class,  
    RecordModule::class,
    BindRecordModule::class,

  ] )
interface RecordComponent {

  @Component.Builder
  interface Builder {
    @BindsInstance
    fun application(application: Application): Builder

    fun build(): RecordComponent
  }

  fun inject(app: RecordApplication)

完成后点击Make Module,Dagger会自动生成类DaggerRecordComponent

4. 重写Application,配置Component

class RecordApplication: Application(), HasActivityInjector, HasSupportFragmentInjector {
  
  override fun onCreate() {
    DaggerRecordComponent.builder().
      .application(this)
      .build()
      .inject(this)
      super.onCreate()
  }

  @Inject
  internal lateinit var activityDispatchingAndroidInjector: DispatchingAndroidInjector<Android>

  override fun activityInjector(): AndroidInjector<Android> {
    return activityDispatchingAndroidInjector
  }

  @Inject
  internal lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>

  override fun supportFragmentInjector(): AndroidInjector<Fragment> {
    return fragmentDispatchingAndroidInjector
  }
}

三. 使用

1. Activity中使用

AndroidInjection.inject(this)可以放在onAttach或者onCreate方法中初始化,只要在使用dagger初始化的地方之前调用即可。
HasSupportFragmentInjector可要可不要,原因未知。
class MainActivity: AppCompatActivity, HasSupportFragmentInjector {

  // use inject anotation to init instance, do not use private, otherwise the param will not init
  @Inject
  lateinit var recordContract: RecordContract

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // pass activity instance to dagger for init the param
    AndroidInjection.inject(this)

    // use the instance function directily
    val name = recordContract.getName()
  }

  @Inject
  internal lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>

  override fun supportFragmentInjector(): AndroidInjector<Fragment> {
    return fragmentDispatchingAndroidInjector
  } }

2. Fragment中使用

 AndroidInjection.inject(this)可以放在onAttach或者onCreate方法中初始化,只要在使用dagger初始化的地方之前调用即可。

class HomeFragment: Fragment() {

  // use inject anotation to init instance, do not use private, otherwise the param will not init
  @Inject
  lateinit var recordContract: RecordContract
    

  override fun onAttach(context: Context) {
    super.onAttach(context)
    // pass activity instance to dagger for init the param
    AndroidInjection.inject(this)
  } }

 

end