本文对系列的第一篇文章中的例子进行了分析总结。

本文首发: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两个集合,还用到了@Moduleincludes属性用于引入其它的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@Modulepublic 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类:

@Modulepublic 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方法完成了对成员变量的注入。

@Betapublic 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中所需的依赖注入。

@Betapublic 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类型,DispatchingAndroidInjector用于Android框架类型实例的成员变量的注入,首先对构造方法传入的两个集合进行了合并,然后在注入时根据类名从集合中获取对应实现类完成成员变量的注入。

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

更多相关文章

  1. Android基本组件__文本框和编辑框
  2. Android中EditText 设置 imeOptions 无效问题的解决方法
  3. Android有两种方法检测USB设备插入
  4. android android屏幕禁止休眠和锁屏的方法
  5. Android向服务器传接和接收数据的方法汇总
  6. android spinner默认样式不支持换行和修改字体样式 的解决方法
  7. [Android][Android Studio] *.jar 与 *.aar 的生成与*.aar导入项

随机推荐

  1. Professional Android(安卓)2 Developmen
  2. 2015-10-30-03-Android Log使用心得
  3. Android:adb发送系统广播及自定义广播
  4. Android 手机制式和网络类型 GSM/EDGE/CD
  5. RecyclerView源码分析一之简单介绍
  6. android:clickable="false"无效问题
  7. Android数字签名解析(三)
  8. android 不同drawable文件对应的dpi值,和
  9. Android Service示例
  10. android Myeclipse7.5运行,HelloWrold,运