Dagger2 Android --- 注解&注入流程分析篇
本篇的分析基于前一篇基础使用:
Dagger2 Android --- 基础使用篇
注解分析
上一篇我们知道使用Dagger Android有这几个步骤:
- 自定义Application继承DaggerApplication
- 创建MainComponent
- 创建ActivityBindingModule,SubComponent为MainComponent
- 创建AppComponent,modules为AndroidSupportInjectionModule.class,ActivityBindingModule.class
- make project,将生成的DaggerAppComponent传给自定义Application
- 在MainActivity的onCreate中,使用AndroidInjection.inject(this)实现注入,实现了对象的绑定(也可以让activity继承DaggerActivity,省略这步)
#自定义Application继承DaggerApplication
DemoApp代码:
public class DemoApp extends DaggerApplication {
@Override
protected AndroidInjector applicationInjector() {
//需要返回DaggerAppComponent给DaggerApplication
return DaggerAppComponent.builder().create(this);
}
}
这一步没有使用任何注解:重点都在DaggerApplication中。那我们就关注下这个类做了什么事情。
DaggerApplication源码:
@Beta
public abstract class DaggerApplication extends Application
implements HasActivityInjector,
HasFragmentInjector,
HasServiceInjector,
HasBroadcastReceiverInjector,
HasContentProviderInjector {
@Inject DispatchingAndroidInjector activityInjector;
@Inject DispatchingAndroidInjector broadcastReceiverInjector;
@Inject DispatchingAndroidInjector fragmentInjector;
@Inject DispatchingAndroidInjector serviceInjector;
@Inject DispatchingAndroidInjector contentProviderInjector;
private volatile boolean needToInject = true;
@Override
public void onCreate() {
super.onCreate();
injectIfNecessary();
}
@ForOverride
protected abstract AndroidInjector applicationInjector();
private void injectIfNecessary() {
if (needToInject) {
synchronized (this) {
if (needToInject) {
@SuppressWarnings("unchecked")
AndroidInjector applicationInjector =
(AndroidInjector) applicationInjector();
applicationInjector.inject(this);
if (needToInject) {
throw new IllegalStateException(
"The AndroidInjector returned from applicationInjector() did not inject the "
+ "DaggerApplication");
}
}
}
}
}
@Inject
void setInjected() {
needToInject = false;
}
@Override
public DispatchingAndroidInjector activityInjector() {
return activityInjector;
}
...
}
源码主要做了两件事:
- 提供四大组件及Fragment的注解分发器:DispatchingAndroidInjector
- 在onCreate时,且需要注入时,调用
applicationInjector.inject(this);
实现注入
那applicationInjector是什么时候创建的呢?
@ForOverride
protected abstract AndroidInjector applicationInjector();
在我们继承DaggerApplication会默认实现该方法,并且将实现了AndroidInjector
那实现了AndroidInjector
这个问题先放一放,稍后分析,我们看第二步
MainComponent
模板代码,泛型为需要注入的类:
@Subcomponent
public interface MainComponent extends AndroidInjector {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder{}
}
这边用到了两个注解:
-
SubComponent
使用SubComponet是为了继承父类的依赖图,父类中使用注解提供依赖的对象,在MainComponent中,同样可以使用。
同时会生成
XXXComponentImpl
的final类private final class MainComponentImpl implements MainComponent { private MainComponentImpl(MainComponentBuilder builder) {} @Override public void inject(MainActivity arg0) { injectMainActivity(arg0); } private MainActivity injectMainActivity(MainActivity instance) { DaggerAppCompatActivity_MembersInjector.injectSupportFragmentInjector( instance, DaggerAppComponent.this.getDispatchingAndroidInjectorOfFragment2()); DaggerAppCompatActivity_MembersInjector.injectFrameworkFragmentInjector( instance, DaggerAppComponent.this.getDispatchingAndroidInjectorOfFragment()); MainActivity_MembersInjector.injectStudent(instance, new Student()); return instance; } }
该类中,会通过
inject
方法将MainActivity
和Student
对象进行绑定,将Student
注入到MainActivity中。我们还可以看到,除了注入了Student之外,还注入了Fragment和SupportFragment。
-
SubComponent.Builder
使用了该注解,会生成
XXXComponentBuilder
的final类,private final class MainComponentBuilder extends MainComponent.Builder { private MainActivity seedInstance; @Override public MainComponent build() { if (seedInstance == null) { throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set"); } return new MainComponentImpl(this); } @Override public void seedInstance(MainActivity arg0) { this.seedInstance = Preconditions.checkNotNull(arg0); } }
这个类比较重要,其中持有了MainActivity实例。
通过seedInstance传入MainActivity,同时通过build创建MainComponentImpl,这样MainComponentImpl也就拥有了MainActivity实例。
那么seedInstance又是在什么地方调用的呢?
-
AndroidInjector
MainComponentImpl
实现了MainComponent
,MainComponentBuilder
又继承了抽象类MainComponent.Builder
。是不是有点眼熟,对!就是我们刚才创建的MainComponent。MainComponent又继承了AndroidInjector接口。
我们再看下MainComponent代码:
@Subcomponent public interface MainComponent extends AndroidInjector
{ @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder {} } 所以先看AndroidInjector源码:
@Beta public interface AndroidInjector
{ void inject(T instance); interface Factory { AndroidInjector create(T instance); } abstract class Builder implements AndroidInjector.Factory { @Override public final AndroidInjector create(T instance) { seedInstance(instance); return build(); } @BindsInstance public abstract void seedInstance(T instance); public abstract AndroidInjector build(); } } 定义了一个inject方法实现注入;一个工厂类,用来创建该对象。这里就是Dagger2 Android的核心了:面向接口编程,移除被注入者对注入者的依赖
这里通过调用create传入需要的目标对象,并通过seedInstance设置,然后再调用build方法。
因为 MainComponentBuilder 继承了 Factory,所有也就是调用其内部的build方法,build做了什么事?? --> 可以翻到上面看看
这边用到一个比较重要的注解: @BindsInstance
添加了该注解的方法,会默认在子类里面生成一个
T
类型的对象,同时在 seedInstance 方法里面进行复制private final class MainComponentBuilder extends MainComponent.Builder { private MainActivity seedInstance; ... @Override public void seedInstance(MainActivity arg0) { this.seedInstance = Preconditions.checkNotNull(arg0); } }
这两块代码就是通过该注解实现的。现在再来通过这张图梳理一下:
创建ActivityBindingModule
还是先看下代码:
@Module(subcomponents = {MainComponent.class})
public abstract class ActivityBindingModule {
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory bindMainActivityInjectorFactory(MainComponent.Builder builder);
}
这边用到了5个注解:
- Module,subcomponents:这两个应该都知道了
- Binds:比较重要的一个注解,告诉dagger,参数是实现了AndroidInjector.Factory接口的类,生成代码的时候会去遍历添加了Inject注解的类,查看是否实现了该接口,然后动态生成;当然也可以通过@Providers和new实现
- IntoMap,ActivityKey:这两个是配对使用的,意思就是将生成的MainComponent.Builder对象放入到Map中,key为ActivityKey(除了ActivityKey,还有StringKey、booleanKey等等)
这一步的作用就是统一管理注入 Builder 类。
下面我们看下生成的代码,验证下刚才的分析:
public final class DaggerAppComponent implements AppComponent {
private Provider mainComponentBuilderProvider;
...
private Map, Provider>>
getMapOfClassOfAndProviderOfFactoryOf() {
return Collections
., Provider>>
singletonMap(MainActivity.class, (Provider) mainComponentBuilderProvider);
}
...
}
确实如此:
使用Binds最终也是通过Provider提供的对象,然后再存入MapBuilder中,等待后续使用。
AppComponent类
AppComponent类:
@Component(modules = {
AndroidSupportInjectionModule.class,
ActivityBindingModule.class
})
public interface AppComponent extends AndroidInjector {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder {
}
}
这边有个AndroidSupportInjectionModule
,继承自AndroidInjectionModule
,这个是干嘛用的呢?
AndroidInjectionModule源码:
@Beta
@Module
public abstract class AndroidInjectionModule {
@Multibinds
abstract Map, AndroidInjector.Factory>
activityInjectorFactories();
@Multibinds
abstract Map, AndroidInjector.Factory>
fragmentInjectorFactories();
@Multibinds
abstract Map, AndroidInjector.Factory>
serviceInjectorFactories();
@Multibinds
abstract Map<
Class, AndroidInjector.Factory>
broadcastReceiverInjectorFactories();
@Multibinds
abstract Map<
Class, AndroidInjector.Factory>
contentProviderInjectorFactories();
private AndroidInjectionModule() {}
}
又有点熟悉了,和我们刚才分析的ActivityBindingModule
有点类似。
这个module的作用:
- 通过ActivityBindingModule生成并保存了所有的AcitivtyBuilder到Map中
- 然后通过这个module将Map提供给AppComponent
再来看下生成的DaggerAppComponent:
public final class DaggerAppComponent implements AppComponent {
private Provider mainComponentBuilderProvider;
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
public static AppComponent.Builder builder() {
return new Builder();
}
private Map, Provider>>
getMapOfClassOfAndProviderOfFactoryOf() {
return Collections
., Provider>>
singletonMap(MainActivity.class, (Provider) mainComponentBuilderProvider);
}
private DispatchingAndroidInjector getDispatchingAndroidInjectorOfActivity() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
getMapOfClassOfAndProviderOfFactoryOf());
}
...
private DispatchingAndroidInjector
getDispatchingAndroidInjectorOfFragment2() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
Collections
.,
Provider>>
emptyMap());
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.mainComponentBuilderProvider =
new Provider() {
@Override
public MainComponent.Builder get() {
return new MainComponentBuilder();
}
};
}
@Override
public void inject(DemoApp arg0) {
injectDemoApp(arg0);
}
private DemoApp injectDemoApp(DemoApp instance) {
DaggerApplication_MembersInjector.injectActivityInjector(
instance, getDispatchingAndroidInjectorOfActivity());
...
return instance;
}
private static final class Builder extends AppComponent.Builder {
private DemoApp seedInstance;
@Override
public AppComponent build() {
if (seedInstance == null) {
throw new IllegalStateException(DemoApp.class.getCanonicalName() + " must be set");
}
return new DaggerAppComponent(this);
}
@Override
public void seedInstance(DemoApp arg0) {
this.seedInstance = Preconditions.checkNotNull(arg0);
}
}
private final class MainComponentBuilder extends MainComponent.Builder {
...
}
private final class MainComponentImpl implements MainComponent {
...
}
}
代码有点多,所有我们就从入口开始看:
DaggerAppComponent.builder().create(this);
builder().create()
,还记得上面的图吗,注入模板类就是通过这个调用生成的。
一步一步看create的执行流程,可以看到两行关键代码:
- new DaggerAppComponent(this);
- new MainComponentBuilder();
到这边,所有的依赖图谱都已经构建完成。
注入的最终实现 inject
1. 注入到DemoApp
AndroidInjector
@Beta
public abstract class DaggerApplication extends Application
implements HasActivityInjector,
HasFragmentInjector,
HasServiceInjector,
HasBroadcastReceiverInjector,
HasContentProviderInjector {
...
@Override
public void onCreate() {
super.onCreate();
injectIfNecessary();
}
@ForOverride
protected abstract AndroidInjector applicationInjector();
private void injectIfNecessary() {
if (needToInject) {
synchronized (this) {
if (needToInject) {
@SuppressWarnings("unchecked")
AndroidInjector applicationInjector =
(AndroidInjector) applicationInjector();
applicationInjector.inject(this);
if (needToInject) {
throw new IllegalStateException(
"The AndroidInjector returned from applicationInjector() did not inject the "
+ "DaggerApplication");
}
}
}
}
}
}
applicationInjector对象的生成:
public class DemoApp extends DaggerApplication {
@Override
protected AndroidInjector applicationInjector() {
return DaggerAppComponent.builder().create(this);
}
}
还记得之前的疑问吗,AndroidInjector
在DaggerApplication内部可以看到,如果需要注入,就会执行applicationInjector.inject(this)
方法;而DaggerAppComponent正式实现了AndroidInjector的类,却在create的时候已经创建。
2. 注入到MainActivity
调用AndroidInjection.inject(this);
public class MainActivity extends DaggerAppCompatActivity {
@Inject
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidInjection.inject(this);
setContentView(R.layout.activity_main);
}
}
AndroidInjection:
@Beta
public final class AndroidInjection {
...
public static void inject(Activity activity) {
checkNotNull(activity, "activity");
Application application = activity.getApplication();
if (!(application instanceof HasActivityInjector)) {
throw new RuntimeException(
String.format(
"%s does not implement %s",
application.getClass().getCanonicalName(),
HasActivityInjector.class.getCanonicalName()));
}
AndroidInjector activityInjector =
((HasActivityInjector) application).activityInjector();
checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());
activityInjector.inject(activity);
}
}
最终也是通过AndroidInjector
同样在create的时候,已经创建了MainComponentBuilder
, MainComponentBuilder
内部又会创建MainComponentImpl
,而MainComponentImpl
正是实现了AndroidInjector
的类。
所有这里的activityInjector对象肯定是存在的,整个注入流程也就实现了。
流程梳理
可以看出,Dagger Android实现自动注入主要分为两部分:
-
注入代码的生成、依赖图谱的构建
@Beta public interface AndroidInjector
{ ... abstract class Builder implements AndroidInjector.Factory { @Override public final AndroidInjector create(T instance) { seedInstance(instance); return build(); } @BindsInstance public abstract void seedInstance(T instance); public abstract AndroidInjector build(); } }
通过抽象类约束生成Dagger注入模板代码,在Application中调用create的时候,会解析依赖图谱并生成所有的注入模板代码
-
注入的实现
@Beta public interface AndroidInjector
{ void inject(T instance); interface Factory { AndroidInjector create(T instance); } abstract class Builder implements AndroidInjector.Factory { @Override public final AndroidInjector create(T instance) { seedInstance(instance); return build(); } @BindsInstance public abstract void seedInstance(T instance); public abstract AndroidInjector build(); } } 通过调用
inject
传入需要使用的对象。
新注解使用
Dagger Android虽然说实现了解耦,但是步骤实在太繁琐了。
所以在2.11之后,有了@ContributesAndroidInjector
注解
新建了一个Module类,声明需要被注入的Activity:
@Module
public abstract class NewActivityBindingModule {
@ContributesAndroidInjector(modules = MainModule.class)
abstract MainActivity mainActivity();
@ContributesAndroidInjector
abstract DetailActivity detailActivity();
}
替换AppComponent里面的modules:
@Component(modules = {
AndroidSupportInjectionModule.class,
NewActivityBindingModule.class,
// ActivityBindingModule.class
})
public interface AppComponent extends AndroidInjector {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder {
}
}
对! 就这么简单,没有了MainComponent,没有了@Binds...,一个注解就帮我们做到了。
make project:
生成了两个ActivityBinding_Module类:
这个类里面又帮我们把重复工作做掉了,尽可能减少使用者的麻烦
@Module(subcomponents = NewActivityBindingModule_DetailActivity.DetailActivitySubcomponent.class)
public abstract class NewActivityBindingModule_DetailActivity {
private NewActivityBindingModule_DetailActivity() {}
@Binds
@IntoMap
@ActivityKey(DetailActivity.class)
abstract AndroidInjector.Factory bindAndroidInjectorFactory(
DetailActivitySubcomponent.Builder builder);
@Subcomponent
public interface DetailActivitySubcomponent extends AndroidInjector {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder {}
}
}