前言
稍微复杂一点的安卓应用基本上都采用了Dagger。但是,很多工程师在学习Dagger的过程中,都抱怨学习曲线很陡峭,上手不容易。究其原因,主要是因为Dagger在编译阶段自动生成了很多代码。而通常情况下,工程师是不会阅读或者理解这些代码的。这就导致了许多安卓工程师只会机械地照搬Dagger的示例教程,而不能从原理上深入理解Dagger的实现。因此,在很多项目中,Dagger无法发挥出它的全部优势,有时甚至会被用错。
为了解决上述问题,我们尝试对Dagger进行源码级别的剖析,以此加深对Dagger的理解。
项目概览
本文将基于一个叫DaggerBasic的项目进行源码分析。这个项目包含了MainActivity、MainViewModel、MainComponent和MainModule。各个类之间的关系图如下所示。
经过编译之后,Dagger会自动生成如下类文件:
- DaggerMainComponent:MainComponent的实现类,提供MainActivity所需的依赖对象。
- MainViewModel_Factory:MainViewModel的工厂类,负责创建MainViewModel。
- MainActivity_MembersInjector:负责向MainActivity注入依赖对象的类。
- MainModule_ProvideSharedPreferencesFactory:负责提供SharedPreferences的工厂类。
接下来我们就逐个分析一下上述生成的类及其功能。
DaggerMainComponent
MainComponent是MainActivity对应的依赖关系图,所有MainActivity依赖的对象,都可以通过MainComponent获得。为了让Dagger能够提供这些对象,开发者需要创建一个接口,并使用 @Component为其添加注释。而Dagger则会自动为我们生成这个接口的实现。
MainComponent的代码如下所示。
@Component(modules = [MainModule::class])
interface MainComponent {
fun inject(activity: MainActivity)
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): MainComponent
}
}
而DaggerMainComponent则是MainComponent的实现类,代码如下所示。
public final class DaggerMainComponent implements MainComponent {
private final Context context;
private final MainModule mainModule;
private DaggerMainComponent(MainModule mainModuleParam, Context contextParam) {
this.context = contextParam;
this.mainModule = mainModuleParam;
}
public static MainComponent.Factory factory() {
return new Factory();
}
private SharedPreferences getSharedPreferences() {
return MainModule_ProvideSharedPreferencesFactory.provideSharedPreferences(mainModule