Dagger2 中使用 AndroidInjection 优化注入流程

每个 Activity 如果都需要手动inject(this)有点繁琐,com.google.dagger:dagger-android中包含AndroidInjection类可以优化注册。

1.在 BaseActivity 中注册

1
2
3
4
5
6
abstract class BaseActivity:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
}
}

注意一定要在super.onCreate(savedInstanceState)之前。其他 Activity 继承 BaseActivity 即可。
同理,BaseFragment 也要这样操作,大同小异。这里以 v4 包的 Fragment 举例:

1
2
3
4
5
6
abstract class BaseFragment:Fragment() {
override fun onAttach(context: Context?) {
AndroidSupportInjection.inject(this)
super.onAttach(context)
}
}

与 Activity 不同,这里在 onAttach 中注册。

2.创建 MainActivitySub

1
2
3
4
5
@Subcomponent(modules = [(StudentModule::class)])
interface MainActivitySub : AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder:AndroidInjector.Builder<MainActivity>()
}

这里多说几句,StudentModule 是 Student 类对应的 Module,Student 类需要注入 MainActivity,MainActivity 继承自 BaseActivity。这几个类简单就不贴了,详情见 源码
如果项目中有 Fragment,那么它对应的 Sub 接口这样写:

1
2
3
4
5
@Subcomponent(modules = [(PersonModule::class)])
interface TestFragmentSub:AndroidInjector<TestFragment>{
@Subcomponent.Builder
abstract class Builder:AndroidInjector.Builder<TestFragment>()
}

上面这两个接口都使用了 Builder 模式。

3.创建 ActivityModule

1
2
3
4
5
6
7
@Module(subcomponents = [(MainActivitySub::class)])
abstract class ActivityModule {
@Binds
@IntoMap
@ActivityKey(MainActivity::class)
abstract fun bindMainActivity(builder: MainActivitySub.Builder): AndroidInjector.Factory<out Activity>
}
  • 所有 Activity 都要在 ActivityModule 中添加:

    1
    @ActivityKey(XXXActivity::class)
  • 每个 Activity 都要建立对应的 XXXActivitySub 接口(上面第 2 步),而且这些 XXXActivitySub 接口都要添加到 ActivityModule 的subcomponents中:

    1
    @Module(subcomponents = [(XXXActivitySub::class),(YYYActivitySub::class)])

FragmentModule 也是一样的套路

1
2
3
4
5
6
7
@Module(subcomponents = [(TestFragmentSub::class)])
abstract class FragmentModule {
@Binds
@IntoMap
@FragmentKey(TestFragment::class)
abstract fun bindTestFragment(builder: TestFragmentSub.Builder): AndroidInjector.Factory<out Fragment>
}

4.创建 ApplicationSub

1
2
3
4
@Component(modules = [(ActivityModule::class), (FragmentModule::class)])
interface ApplicationSub {
fun inject(app: MyApp)
}

ApplicationSub 管理 ActivityModule 和 FragmentModule,而这两个类管理所有的 Activity 和 Fragment,这样,就只需要在 Application 中初始化就好了。

5.初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyApp : Application(), HasActivityInjector, HasSupportFragmentInjector  {

@Inject
lateinit var activityInjector: DispatchingAndroidInjector<Activity>
@Inject
lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

override fun onCreate() {
super.onCreate()
DaggerApplicationSub.create().inject(this)
}

override fun activityInjector(): DispatchingAndroidInjector<Activity> {
return activityInjector
}

override fun supportFragmentInjector(): DispatchingAndroidInjector<Fragment> {
return fragmentInjector
}
}

6.其他说明

  • 我使用的开发环境是gradle:3.1.2 + kotlin_version = '1.2.30',需要在 app.gradle 里面添加apply plugin: 'kotlin-kapt'

  • 使用针对 Android 的 dagger 地址:

    1
    2
    3
    kapt 'com.google.dagger:dagger-compiler:2.12'
    implementation 'com.google.dagger:dagger-android:2.12'
    implementation 'com.google.dagger:dagger-android-support:2.12'
  • Rebuild 的时候会提示如下红色日志,这个不影响,可以直接运行项目:

    1
    2
    3
    4
    5
    Folder D:\workspace\Dagger2Sample-master\app\build\generated\source\kaptKotlin\debug

    Folder D:\workspace\Dagger2Sample-master\app\build\generated\source\kaptKotlin\release

    3rd-party Gradle plug-ins may be the cause

最后,
源码地址


其他几篇的链接:
Dagger2 中的 Qualifier
Dagger2 中的 Scope、dependencies
Dagger2 中的 SubComponent
Dagger2 中的 Binds、IntoSet、IntoMap