本文对系列的第一篇文章中的例子进行了分析总结。
本文首发: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{ AndroidInjectorcreate(T instance); } abstract class Builderimplements AndroidInjector.Factory{ @Override public final AndroidInjectorcreate(T instance) { seedInstance(instance); return build(); } @BindsInstance public abstract void seedInstance(T instance); public abstract AndroidInjectorbuild(); } }
AndroidSupportInjectionModule中用@Multibinds
注解声明了Support中Fragment的多绑定,包括Fragment的Class的key和String的key两个集合,还用到了@Module
的includes
属性用于引入其它的Module进行组合:
@Beta @Module(includes = AndroidInjectionModule.class) public abstract class AndroidSupportInjectionModule { @Multibinds abstract Map<class, AndroidInjector.Factory> supportFragmentInjectorFactories(); @Multibinds abstract Map<string, androidinjector.factory> supportFragmentInjectorFactoriesWithStringKeys(); private AndroidSupportInjectionModule() {} }
AndroidInjectionModule类中和AndroidSupportInjectionModule类似,声明了Android中四大组件Activity、Service、BroadcastReceiver、ContentProvider和Fragment的多绑定,只所以需要声明是由于这些Map集合有可能为空。
@Beta @Module public abstract class AndroidInjectionModule { @Multibinds abstract Map<class, AndroidInjector.Factory> activityInjectorFactories(); @Multibinds abstract Map<string, androidinjector.factory> activityInjectorFactoriesWithStringKeys(); @Multibinds abstract Map<class, AndroidInjector.Factory> fragmentInjectorFactories(); @Multibinds abstract Map<string, androidinjector.factory> fragmentInjectorFactoriesWithStringKeys(); @Multibinds abstract Map<class, AndroidInjector.Factory> serviceInjectorFactories(); @Multibinds abstract Map<string, androidinjector.factory> serviceInjectorFactoriesWithStringKeys(); @Multibinds abstract Map< Class, AndroidInjector.Factory> broadcastReceiverInjectorFactories(); @Multibinds abstract Map<string, androidinjector.factory> broadcastReceiverInjectorFactoriesWithStringKeys(); @Multibinds abstract Map<class, AndroidInjector.Factory> contentProviderInjectorFactories(); @Multibinds abstract Map<string, androidinjector.factory> 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 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 ProviderhomeActivitySubcomponentBuilderProvider; private DaggerAppComponent(Builder builder) { initialize(builder); } public static Builder builder() { return new Builder(); } public static AppComponent create() { return new Builder().build(); } private Map<class, Provider<androidinjector.factory>> getMapOfClassOfAndProviderOfFactoryOf() { return MapBuilder .<class, Provider<androidinjector.factory>> newMapBuilder(1) .put(HomeActivity.class, (Provider) homeActivitySubcomponentBuilderProvider) .build(); } private DispatchingAndroidInjectorgetDispatchingAndroidInjectorOfActivity() { return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector( getMapOfClassOfAndProviderOfFactoryOf(), Collections.<string, provider<androidinjector.factory>>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 ProviderbindPresenterProvider; 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 applicationInjector() { return DaggerAppComponent.create(); } }
DaggerApplication在onCreate方法中调用了我们实现的applicationInjector方法,然后调用inject方法完成了对成员变量的注入。
@Beta public abstract class DaggerApplication extends Application implements HasActivityInjector, HasFragmentInjector, HasServiceInjector, HasBroadcastReceiverInjector, HasContentProviderInjector { @Inject DispatchingAndroidInjectoractivityInjector; @Inject DispatchingAndroidInjectorbroadcastReceiverInjector; @Inject DispatchingAndroidInjectorfragmentInjector; @Inject DispatchingAndroidInjectorserviceInjector; @Inject DispatchingAndroidInjectorcontentProviderInjector; 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") AndroidInjectorapplicationInjector = (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 DispatchingAndroidInjectoractivityInjector() { return activityInjector; } @Override public DispatchingAndroidInjectorfragmentInjector() { return fragmentInjector; } @Override public DispatchingAndroidInjectorbroadcastReceiverInjector() { return broadcastReceiverInjector; } @Override public DispatchingAndroidInjectorserviceInjector() { return serviceInjector; } @Override public AndroidInjectorcontentProviderInjector() { injectIfNecessary(); return contentProviderInjector; } }
DaggerActivity
我们的Activity继承自了DaggerActivity,DaggerActivity类中实现HasFragmentInjector接口用于Fragment的注入,在onCreate方法中使用AndroidInjection类完成了Activity中所需的依赖注入。
@Beta public abstract class DaggerActivity extends Activity implements HasFragmentInjector { @Inject DispatchingAndroidInjectorfragmentInjector; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); } @Override public AndroidInjectorfragmentInjector() { 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())); } AndroidInjectoractivityInjector = ((HasActivityInjector) application).activityInjector(); checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass()); activityInjector.inject(activity); } ... private AndroidInjection() {} }
DispatchingAndroidInjector
DaggerApplication中activityInjector方法返回的是DispatchingAndroidInjector
public final class DispatchingAndroidInjectorimplements 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<string, provider<androidinjector.factory>> injectorFactories; @Inject DispatchingAndroidInjector( Map<class, Provider<factory>> injectorFactoriesWithClassKeys, Map<string, provider<factory>> injectorFactoriesWithStringKeys) { this.injectorFactories = merge(injectorFactoriesWithClassKeys, injectorFactoriesWithStringKeys); } private staticMapmerge( Map<class, V> classKeyedMap, MapstringKeyedMap) { if (classKeyedMap.isEmpty()) { return stringKeyedMap; } Mapmerged = newLinkedHashMapWithExpectedSize(classKeyedMap.size() + stringKeyedMap.size()); merged.putAll(stringKeyedMap); for (Entry<class, V> entry : classKeyedMap.entrySet()) { merged.put(entry.getKey().getName(), entry.getValue()); } return Collections.unmodifiableMap(merged); } @CanIgnoreReturnValue public boolean maybeInject(T instance) { Provider<androidinjector.factory> factoryProvider = injectorFactories.get(instance.getClass().getName()); if (factoryProvider == null) { return false; } @SuppressWarnings("unchecked") AndroidInjector.Factoryfactory = (AndroidInjector.Factory) factoryProvider.get(); try { AndroidInjectorinjector = 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) { Listsuggestions = 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