《天净沙·秋思》
枯藤老树昏鸦,小桥流水人家,古道西风瘦马。
夕阳西下,断肠人在天涯。
-元代,马致远
前言
在前面的文章我们介绍了Dagger2 中的大部分注解的使用,接下来我们从源码角度分析下第一篇文章中例子的原理。
AppComponent
自定义组件AppComponent继承了AndroidInjector接口类,指定了Module类ActivityBindingModule和Dagger2中的AndroidSupportInjectionModule:1
2
3@Component(modules = {ActivityBindingModule.class,AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<App> {
}
AndroidInjector接口中包含一个inject用于注入的方法,和一个抽象Builder类,其中用到了我们在上文中介绍的@BindsInstance
注解,用于将注入的实例绑定到构建的依赖图中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public interface AndroidInjector<T> {
void inject(T instance);
interface Factory<T> {
AndroidInjector<T> create(T instance);
}
abstract class Builder<T> implements AndroidInjector.Factory<T> {
@Override
public final AndroidInjector<T> create(T instance) {
seedInstance(instance);
return build();
}
@BindsInstance
public abstract void seedInstance(T instance);
public abstract AndroidInjector<T> build();
}
}
AndroidSupportInjectionModule中用@Multibinds
注解声明了Support中Fragment的多绑定,包括Fragment的Class的key和String的key两个集合,还用到了@Module
的includes
属性用于引入其它的Module进行组合:1
2
3
4
5
6
7
8
9
10
11
12
13@Beta
@Module(includes = AndroidInjectionModule.class)
public abstract class AndroidSupportInjectionModule {
@Multibinds
abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>>
supportFragmentInjectorFactories();
@Multibinds
abstract Map<String, AndroidInjector.Factory<? extends Fragment>>
supportFragmentInjectorFactoriesWithStringKeys();
private AndroidSupportInjectionModule() {}
}
AndroidInjectionModule类中和AndroidSupportInjectionModule类似,声明了Android中四大组件Activity、Service、BroadcastReceiver、ContentProvider和Fragment的多绑定,只所以需要声明是由于这些Map集合有可能为空。
1 | @Beta |
ActivityBindingModule
下面是我们自定义的用于Activity绑定的Module类:1
2
3
4
5
6
7
8@Module
public abstract class ActivityBindingModule {
@ActivityScope
@ContributesAndroidInjector(modules = HomeModule.class)
abstract HomeActivity contributeHomeActivity();
}
注解@ContributesAndroidInjector
用于为该方法返回类型生成一个AndroidInjector。用在Module中的无参抽象方法上,返回参数为具体的Android框架类型(如:HomeActivity、MyFragment、MyService等),指定的Module将会被安装到生成的Subcomponent上。上面的代码将会生成下面的类:
1 | @Module(subcomponents = ActivityBindingModule_ContributeHomeActivity.HomeActivitySubcomponent.class) |
这里使用了多绑定以Activity的class为key和生成的子组件的Builder类为value绑定到了Map集合中。
DaggerAppComponent
上面类中的多绑定会在生成的Component类中生成提供该集合的方法,以及生成的子组件接口的实现类:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108public final class DaggerAppComponent implements AppComponent {
private Provider<ActivityBindingModule_ContributeHomeActivity.HomeActivitySubcomponent.Builder>
homeActivitySubcomponentBuilderProvider;
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static AppComponent create() {
return new Builder().build();
}
private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
getMapOfClassOfAndProviderOfFactoryOf() {
return MapBuilder
.<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
newMapBuilder(1)
.put(HomeActivity.class, (Provider) homeActivitySubcomponentBuilderProvider)
.build();
}
private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
getMapOfClassOfAndProviderOfFactoryOf(),
Collections.<String, Provider<AndroidInjector.Factory<? extends Activity>>>emptyMap());
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.homeActivitySubcomponentBuilderProvider =
new Provider<
ActivityBindingModule_ContributeHomeActivity.HomeActivitySubcomponent.Builder>() {
@Override
public ActivityBindingModule_ContributeHomeActivity.HomeActivitySubcomponent.Builder
get() {
return new HomeActivitySubcomponentBuilder();
}
};
}
@Override
public void inject(App arg0) {
injectApp(arg0);
}
private App injectApp(App instance) {
DaggerApplication_MembersInjector.injectActivityInjector(
instance, getDispatchingAndroidInjectorOfActivity());
return instance;
}
public static final class Builder {
private Builder() {}
public AppComponent build() {
return new DaggerAppComponent(this);
}
}
private final class HomeActivitySubcomponentBuilder
extends ActivityBindingModule_ContributeHomeActivity.HomeActivitySubcomponent.Builder {
private HomeActivity seedInstance;
@Override
public ActivityBindingModule_ContributeHomeActivity.HomeActivitySubcomponent build() {
if (seedInstance == null) {
throw new IllegalStateException(HomeActivity.class.getCanonicalName() + " must be set");
}
return new HomeActivitySubcomponentImpl(this);
}
@Override
public void seedInstance(HomeActivity arg0) {
this.seedInstance = Preconditions.checkNotNull(arg0);
}
}
private final class HomeActivitySubcomponentImpl
implements ActivityBindingModule_ContributeHomeActivity.HomeActivitySubcomponent {
private Provider<HomeContract.Presenter> bindPresenterProvider;
private HomeActivitySubcomponentImpl(HomeActivitySubcomponentBuilder builder) {
initialize(builder);
}
@SuppressWarnings("unchecked")
private void initialize(final HomeActivitySubcomponentBuilder builder) {
this.bindPresenterProvider = DoubleCheck.provider((Provider) HomePresenter_Factory.create());
}
@Override
public void inject(HomeActivity arg0) {
injectHomeActivity(arg0);
}
private HomeActivity injectHomeActivity(HomeActivity instance) {
DaggerActivity_MembersInjector.injectFragmentInjector(
instance, DaggerAppComponent.this.getDispatchingAndroidInjectorOfFragment());
HomeActivity_MembersInjector.injectMPresenter(instance, bindPresenterProvider.get());
return instance;
}
}
}
DaggerApplication
我们在Application中继承了DaggerApplication类,并实现了applicationInjector方法返回了AppComponent类的实例:
1 | public class App extends DaggerApplication { |
DaggerApplication在onCreate方法中调用了我们实现的applicationInjector方法,然后调用inject方法完成了对成员变量的注入。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74@Beta
public abstract class DaggerApplication extends Application
implements HasActivityInjector,
HasFragmentInjector,
HasServiceInjector,
HasBroadcastReceiverInjector,
HasContentProviderInjector {
@Inject DispatchingAndroidInjector<Activity> activityInjector;
@Inject DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector;
@Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
@Inject DispatchingAndroidInjector<Service> serviceInjector;
@Inject DispatchingAndroidInjector<ContentProvider> contentProviderInjector;
private volatile boolean needToInject = true;
@Override
public void onCreate() {
super.onCreate();
injectIfNecessary();
}
@ForOverride
protected abstract AndroidInjector<? extends DaggerApplication> applicationInjector();
private void injectIfNecessary() {
if (needToInject) {
synchronized (this) {
if (needToInject) {
@SuppressWarnings("unchecked")
AndroidInjector<DaggerApplication> applicationInjector =
(AndroidInjector<DaggerApplication>) 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<Activity> activityInjector() {
return activityInjector;
}
@Override
public DispatchingAndroidInjector<Fragment> fragmentInjector() {
return fragmentInjector;
}
@Override
public DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
return broadcastReceiverInjector;
}
@Override
public DispatchingAndroidInjector<Service> serviceInjector() {
return serviceInjector;
}
@Override
public AndroidInjector<ContentProvider> contentProviderInjector() {
injectIfNecessary();
return contentProviderInjector;
}
}
DaggerActivity
我们的Activity继承自了DaggerActivity,DaggerActivity类中实现HasFragmentInjector接口用于Fragment的注入,在onCreate方法中使用AndroidInjection类完成了Activity中所需的依赖注入。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16@Beta
public abstract class DaggerActivity extends Activity implements HasFragmentInjector {
@Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
@Override
public AndroidInjector<Fragment> fragmentInjector() {
return fragmentInjector;
}
}
AndroidInjection
AndroidInjection是一个工具类,用于对Android框架中Activity、Fragment、Service、BroadcastReceiver、ContentProvider进行依赖注入。AndroidInjection会从Application中获取activityInjector方法的值进行依赖注入。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public final class AndroidInjection {
private static final String TAG = "dagger.android";
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<Activity> activityInjector =
((HasActivityInjector) application).activityInjector();
checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());
activityInjector.inject(activity);
}
...
private AndroidInjection() {}
}
DispatchingAndroidInjector
DaggerApplication中activityInjector方法返回的是DispatchingAndroidInjector1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87public final class DispatchingAndroidInjector<T> implements AndroidInjector<T> {
private static final String NO_SUPERTYPES_BOUND_FORMAT =
"No injector factory bound for Class<%s>";
private static final String SUPERTYPES_BOUND_FORMAT =
"No injector factory bound for Class<%1$s>. Injector factories were bound for supertypes "
+ "of %1$s: %2$s. Did you mean to bind an injector factory for the subtype?";
private final Map<String, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories;
@Inject
DispatchingAndroidInjector(
Map<Class<? extends T>, Provider<Factory<? extends T>>> injectorFactoriesWithClassKeys,
Map<String, Provider<Factory<? extends T>>> injectorFactoriesWithStringKeys) {
this.injectorFactories = merge(injectorFactoriesWithClassKeys, injectorFactoriesWithStringKeys);
}
private static <C, V> Map<String, V> merge(
Map<Class<? extends C>, V> classKeyedMap, Map<String, V> stringKeyedMap) {
if (classKeyedMap.isEmpty()) {
return stringKeyedMap;
}
Map<String, V> merged =
newLinkedHashMapWithExpectedSize(classKeyedMap.size() + stringKeyedMap.size());
merged.putAll(stringKeyedMap);
for (Entry<Class<? extends C>, V> entry : classKeyedMap.entrySet()) {
merged.put(entry.getKey().getName(), entry.getValue());
}
return Collections.unmodifiableMap(merged);
}
@CanIgnoreReturnValue
public boolean maybeInject(T instance) {
Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
injectorFactories.get(instance.getClass().getName());
if (factoryProvider == null) {
return false;
}
@SuppressWarnings("unchecked")
AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
try {
AndroidInjector<T> injector =
checkNotNull(
factory.create(instance), "%s.create(I) should not return null.", factory.getClass());
injector.inject(instance);
return true;
} catch (ClassCastException e) {
throw new InvalidInjectorBindingException(
String.format(
"%s does not implement AndroidInjector.Factory<%s>",
factory.getClass().getCanonicalName(), instance.getClass().getCanonicalName()),
e);
}
}
@Override
public void inject(T instance) {
boolean wasInjected = maybeInject(instance);
if (!wasInjected) {
throw new IllegalArgumentException(errorMessageSuggestions(instance));
}
}
@Beta
public static final class InvalidInjectorBindingException extends RuntimeException {
InvalidInjectorBindingException(String message, ClassCastException cause) {
super(message, cause);
}
}
private String errorMessageSuggestions(T instance) {
List<String> suggestions = new ArrayList<>();
for (Class<?> clazz = instance.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
if (injectorFactories.containsKey(clazz.getCanonicalName())) {
suggestions.add(clazz.getCanonicalName());
}
}
return suggestions.isEmpty()
? String.format(NO_SUPERTYPES_BOUND_FORMAT, instance.getClass().getCanonicalName())
: String.format(
SUPERTYPES_BOUND_FORMAT, instance.getClass().getCanonicalName(), suggestions);
}
}
总结
Dagger2使用多绑定和子组件功能将需要成员变量注入类的class和生成子组件实现类存入到Application的Map集合中,在Activity#onCreate方法中通过类名从Map集合中获取对应实现类完成了成员变量注入。
参考
- https://google.github.io/dagger/
- https://www.jianshu.com/p/24af4c102f62
- http://www.cnblogs.com/tiantianbyconan/p/5092083.html