本文对系列的第一篇文章中的例子进行了分析总结。
本文首发:http://yuweiguocn.github.io/
《天净沙·秋思》
枯藤老树昏鸦,小桥流水人家,古道西风瘦马。
夕阳西下,断肠人在天涯。
-元代,马致远
Dagger 2 在 Android 上的使用(一)
Dagger 2 在 Android 上的使用(二)
Dagger 2 在 Android 上的使用(三)
Dagger 2 在 Android 上的使用(四)
Dagger 2 在 Android 上的使用(五)
前言
在前面的文章我们介绍了Dagger2 中的大部分注解的使用,接下来我们从源码角度分析下第一篇文章中例子的原理。
AppComponent
自定义组件AppComponent继承了AndroidInjector接口类,指定了Module类ActivityBindingModule和Dagger2中的AndroidSupportInjectionModule:
@Component(modules = {ActivityBindingModule.class,AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector {
}
AndroidInjector接口中包含一个inject用于注入的方法,和一个抽象Builder类,其中用到了我们在上文中介绍的@BindsInstance
注解,用于将注入的实例绑定到构建的依赖图中。
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();
}
}
AndroidSupportInjectionModule中用@Multibinds
注解声明了Support中Fragment的多绑定,包括Fragment的Class的key和String的key两个集合,还用到了@Module
的includes
属性用于引入其它的Module进行组合:
@Beta
@Module(includes = AndroidInjectionModule.class)
public abstract class AndroidSupportInjectionModule {
@Multibinds
abstract Map, AndroidInjector.Factory extends Fragment>>
supportFragmentInjectorFactories();
@Multibinds
abstract Map>
supportFragmentInjectorFactoriesWithStringKeys();
private AndroidSupportInjectionModule() {}
}
AndroidInjectionModule类中和AndroidSupportInjectionModule类似,声明了Android中四大组件Activity、Service、BroadcastReceiver、ContentProvider和Fragment的多绑定,只所以需要声明是由于这些Map集合有可能为空。
@Beta
@Module
public abstract class AndroidInjectionModule {
@Multibinds
abstract Map, AndroidInjector.Factory extends Activity>>
activityInjectorFactories();
@Multibinds
abstract Map>
activityInjectorFactoriesWithStringKeys();
@Multibinds
abstract Map, AndroidInjector.Factory extends Fragment>>
fragmentInjectorFactories();
@Multibinds
abstract Map>
fragmentInjectorFactoriesWithStringKeys();
@Multibinds
abstract Map, AndroidInjector.Factory extends Service>>
serviceInjectorFactories();
@Multibinds
abstract Map>
serviceInjectorFactoriesWithStringKeys();
@Multibinds
abstract Map<
Class extends BroadcastReceiver>, AndroidInjector.Factory extends BroadcastReceiver>>
broadcastReceiverInjectorFactories();
@Multibinds
abstract Map>
broadcastReceiverInjectorFactoriesWithStringKeys();
@Multibinds
abstract Map, AndroidInjector.Factory extends ContentProvider>>
contentProviderInjectorFactories();
@Multibinds
abstract Map>
contentProviderInjectorFactoriesWithStringKeys();
private AndroidInjectionModule() {}
}
ActivityBindingModule
下面是我们自定义的用于Activity绑定的Module类:
@Module
public abstract class ActivityBindingModule {
@ActivityScope
@ContributesAndroidInjector(modules = HomeModule.class)
abstract HomeActivity contributeHomeActivity();
}
注解@ContributesAndroidInjector
用于为该方法返回类型生成一个AndroidInjector。用在Module中的无参抽象方法上,返回参数为具体的Android框架类型(如:HomeActivity、MyFragment、MyService等),指定的Module将会被安装到生成的Subcomponent上。上面的代码将会生成下面的类:
@Module(subcomponents = ActivityBindingModule_ContributeHomeActivity.HomeActivitySubcomponent.class)
public abstract class ActivityBindingModule_ContributeHomeActivity {
private ActivityBindingModule_ContributeHomeActivity() {}
@Binds
@IntoMap
@ActivityKey(HomeActivity.class)
abstract AndroidInjector.Factory extends Activity> bindAndroidInjectorFactory(
HomeActivitySubcomponent.Builder builder);
@Subcomponent(modules = HomeModule.class)
@ActivityScope
public interface HomeActivitySubcomponent extends AndroidInjector {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder {}
}
}
这里使用了多绑定以Activity的class为key和生成的子组件的Builder类为value绑定到了Map集合中。
DaggerAppComponent
上面类中的多绑定会在生成的Component类中生成提供该集合的方法,以及生成的子组件接口的实现类:
public final class DaggerAppComponent implements AppComponent {
private Provider
homeActivitySubcomponentBuilderProvider;
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static AppComponent create() {
return new Builder().build();
}
private Map, Provider>>
getMapOfClassOfAndProviderOfFactoryOf() {
return MapBuilder
., Provider>>
newMapBuilder(1)
.put(HomeActivity.class, (Provider) homeActivitySubcomponentBuilderProvider)
.build();
}
private DispatchingAndroidInjector getDispatchingAndroidInjectorOfActivity() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
getMapOfClassOfAndProviderOfFactoryOf(),
Collections.>>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 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类的实例:
public class App extends DaggerApplication {
@Override
protected AndroidInjector extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.create();
}
}
DaggerApplication在onCreate方法中调用了我们实现的applicationInjector方法,然后调用inject方法完成了对成员变量的注入。
@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 extends DaggerApplication> 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;
}
@Override
public DispatchingAndroidInjector fragmentInjector() {
return fragmentInjector;
}
@Override
public DispatchingAndroidInjector broadcastReceiverInjector() {
return broadcastReceiverInjector;
}
@Override
public DispatchingAndroidInjector serviceInjector() {
return serviceInjector;
}
@Override
public AndroidInjector contentProviderInjector() {
injectIfNecessary();
return contentProviderInjector;
}
}
DaggerActivity
我们的Activity继承自了DaggerActivity,DaggerActivity类中实现HasFragmentInjector接口用于Fragment的注入,在onCreate方法中使用AndroidInjection类完成了Activity中所需的依赖注入。
@Beta
public abstract class DaggerActivity extends Activity implements HasFragmentInjector {
@Inject DispatchingAndroidInjector fragmentInjector;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
@Override
public AndroidInjector fragmentInjector() {
return fragmentInjector;
}
}
AndroidInjection
AndroidInjection是一个工具类,用于对Android框架中Activity、Fragment、Service、BroadcastReceiver、ContentProvider进行依赖注入。AndroidInjection会从Application中获取activityInjector方法的值进行依赖注入。
public 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 activityInjector =
((HasActivityInjector) application).activityInjector();
checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());
activityInjector.inject(activity);
}
...
private AndroidInjection() {}
}
DispatchingAndroidInjector
DaggerApplication中activityInjector方法返回的是DispatchingAndroidInjector
public final class DispatchingAndroidInjector implements AndroidInjector {
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>> injectorFactories;
@Inject
DispatchingAndroidInjector(
Map, Provider>> injectorFactoriesWithClassKeys,
Map>> injectorFactoriesWithStringKeys) {
this.injectorFactories = merge(injectorFactoriesWithClassKeys, injectorFactoriesWithStringKeys);
}
private static Map merge(
Map, V> classKeyedMap, Map stringKeyedMap) {
if (classKeyedMap.isEmpty()) {
return stringKeyedMap;
}
Map merged =
newLinkedHashMapWithExpectedSize(classKeyedMap.size() + stringKeyedMap.size());
merged.putAll(stringKeyedMap);
for (Entry, V> entry : classKeyedMap.entrySet()) {
merged.put(entry.getKey().getName(), entry.getValue());
}
return Collections.unmodifiableMap(merged);
}
@CanIgnoreReturnValue
public boolean maybeInject(T instance) {
Provider> factoryProvider =
injectorFactories.get(instance.getClass().getName());
if (factoryProvider == null) {
return false;
}
@SuppressWarnings("unchecked")
AndroidInjector.Factory factory = (AndroidInjector.Factory) factoryProvider.get();
try {
AndroidInjector 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 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