Dagger2官网:http://google.github.io/dagger/
Githup地址:https://github.com/google/dagger
今天,介绍Dagger2的第二种使用方式,相比上次介绍的第一种使用方式的话,会更加适用于Android工程。
第一步、下载jar包;配置如下:
dependencies {
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
compile 'com.google.dagger:dagger-android:2.x'
compile 'com.google.dagger:dagger-android-support:2.x'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
}
dagger-android-support包是用于support包,如果你工程中没有用到support包,就可以不用下载这个包。
第二步、编写@Component标识的接口,有两种写法;先看第一种写法,代码如下:
@Singleton
@Component(modules = {ApplicationModule.class,
ActivityBindingModule.class,
AndroidSupportInjectionModule.class})
public interface ApplicationComponent extends AndroidInjector<MyMovieApplication> {
DataManager dataManager();
}
与上篇介绍的第一种方式中Component接口的编写,除了必须继承于AndroidInjector< T >
(泛型T必须是这个Component要注入的那个类,这个在后面说明)外,基本一样。
第二种写法:
@Singleton
@Component(modules = {ApplicationModule.class,
ActivityBindingModule.class,
AndroidSupportInjectionModule.class})
public interface ApplicationComponent extends AndroidInjector<MyMovieApplication> {
DataManager dataManager();
@Component.Builder
interface Builder {
@BindsInstance
ApplicationComponent.Builder application(Application application);
ApplicationComponent build();
}
}
比第一种写法多了个注解@BindsInstance(用这个注解标识的方法,必须有个方法参数;而且这个参数实例会被直接放入Component,以提供依赖)和用@Component.Builder
标识的接口;里面有两个方法,application()
和build()
,它们返回类型分别是ApplicationComponent.Builder和ApplicationComponent。是不是好像懂了,其实这个@Component.Builder标识的接口就是用来构建ApplicationComponent实例的,有点类似于AlertDialog.Builder。
/**
* A builder for a component. Components may have a single nested static abstract class or
* interface annotated with {@code @Component.Builder}. If they do, then the component's
* generated builder will match the API in the type. Builders must follow some rules:
*
* - A single abstract method with no arguments must exist, and must return the component.
* (This is typically the {@code build()} method.)
*
- All other abstract methods must take a single argument and must return void,
* the Builder type, or a supertype of the builder.
*
- Each component dependency must have an abstract setter method.
*
- Each module dependency that Dagger can't instantiate itself (e.g, the module
* doesn't have a visible no-args constructor) must have an abstract setter method.
* Other module dependencies (ones that Dagger can instantiate) are allowed, but not required.
*
- Non-abstract methods are allowed, but ignored as far as validation and builder generation
* are concerned.
*
*
* For example, this could be a valid Component with a Builder:
* {@literal @}Component(modules = {BackendModule.class, FrontendModule.class})
* interface MyComponent {
* MyWidget myWidget();
*
* {@literal @}Component.Builder
* interface Builder {
* MyComponent build();
* Builder backendModule(BackendModule bm);
* Builder frontendModule(FrontendModule fm);
* }
* }
*/
@Target(TYPE)
@Documented
@interface Builder {}
上面就是官方的英文文档,@Builder不仅可以用来标识接口也可以标识静态的抽象类,使用这注解的时候有五条规则。
1、必须存在一个不带参数的方法,比如在ApplicationComponent.Builder接口中的build()
2、除了上面提到的必须存在一个不带参数的方法外,其他方法必须带一个参数,并且返回类型只能是void、这个注解标识的接口类型或这个接口的父类型
3、组件所依赖的组件,必须有个setter method;举个例子:
@Component(dependencies = ApplicationComponent.class)
public interface ActivityComponent extends AndroidInjector<MovieActivity> {
......
@Component.Builder
interface Builder {
.......
Builder applicationComponent(ApplicationComponent ac);
.......
}
}
4、组件所依赖的module,必须有个setter method。在上面ApplicationComponent接口中,有三个module类。那在Builder接口中为什么没有设置setter method?首先,来看ApplicationModule类文件;
@Module
public class ApplicationModule {
@Provides
@Singleton
Request provideRequest() {
return new NetworkManagerService().createRetrofit();
}
}
ApplicationModule类中没有带参数的构造方法。再来看,编译后,生成的部分代码:
private static final class Builder implements ApplicationComponent.Builder {
private ApplicationModule applicationModule;
private Application application;
@Override
public ApplicationComponent build() {
if (applicationModule == null) {
this.applicationModule = new ApplicationModule();
}
if (application == null) {
throw new IllegalStateException(Application.class.getCanonicalName() + " must be set");
}
return new DaggerApplicationComponent(this);
}
@Override
public Builder application(Application application) {
this.application = Preconditions.checkNotNull(application);
return this;
}
}
是不是懂了,就是因为ApplicationModule类中没有带参数的构造方法;生成的代码就可以直接new ApplicationModule()
,也不用setter method。如果我给ApplicationModule增加个带参数的构造方法,那该怎么写呢?如下:
@Component.Builder
interface Builder {
.......
Builder applicationModule(ApplicationModule am);
.......
}
如果@Module标识的是抽象类的话,setter method也不用设置,设置了反而会编译报错。比如ActivityBindingModule.class和AndroidSupportInjectionModule.class。所以,组件所依赖的module,如果是带参数的构造方法而且不是抽象类,才必须setter method
5、非抽象方法是允许的,但是对于验证和代码生成器而言,它们是被忽略的。也就是说,写了非抽象方法会被直接忽略掉。(@Builder不仅可以用来标识接口也可以标识静态的抽象类)
刚才提到ActivityBindingModule.class和AndroidSupportInjectionModule.class都是抽象类。
AndroidSupportInjectionModule类的源码:
package dagger.android.support;
.......
@Beta
@Module(includes = AndroidInjectionModule.class)
public abstract class AndroidSupportInjectionModule {
@Multibinds
abstract Map, AndroidInjector.Factory extends Fragment>>
supportFragmentInjectorFactories();
private AndroidSupportInjectionModule() {}
}
@Module的属性includes = AndroidInjectionModule.class,其作用就是把AndroidInjectionModule类中的方法放到AndroidSupportInjectionModule类中,相当于融合。关于@Multibinds的作用不太好说,看官方文档吧。再看看 AndroidInjectionModule类的源码:
package dagger.android;
.........
@Beta
@Module
public abstract class AndroidInjectionModule {
@Multibinds
abstract Map, AndroidInjector.Factory extends Activity>>
activityInjectorFactories();
@Multibinds
abstract Map, AndroidInjector.Factory extends Fragment>>
fragmentInjectorFactories();
@Multibinds
abstract Map, AndroidInjector.Factory extends Service>>
serviceInjectorFactories();
@Multibinds
abstract Map<
Class extends BroadcastReceiver>, AndroidInjector.Factory extends BroadcastReceiver>>
broadcastReceiverInjectorFactories();
@Multibinds
abstract Map<
Class extends ContentProvider>, AndroidInjector.Factory extends ContentProvider>>
contentProviderInjectorFactories();
private AndroidInjectionModule() {}
}
这两类文件中的方法返回类型都是Map(这两个类文件的作用,之后代码分析的时候说明);两类文件分别在dagger.android和dagger.android.support包下,是不需要我们编写的。但是必须在@Component标识的接口中使用一个,我这用的是AndroidSupportInjectionModule,是因为我的Activity是继承于support包的;如果不是,你可以用AndroidInjectionModule,反正二者选一。
ActivityBindingModule类的源码:
@Module
public abstract class ActivityBindingModule {
@ActivityScope
@ContributesAndroidInjector
abstract MainActivity mainActivity();
@ActivityScope
@ContributesAndroidInjector
abstract FilmmakerActivity filmmakerActivity();
@ActivityScope
@ContributesAndroidInjector
abstract MovieActivity movieActivity();
@ActivityScope
@ContributesAndroidInjector
abstract SearchActivity searchActivity();
@ActivityScope
@ContributesAndroidInjector
abstract SortActivity sortActivity();
}
有5个抽象方法,返回类型都是Activity;而且,我这个工程又是这5个activity需要注入;也就说这个类是帮助需要注入的类自动生成对应的Component类的。在dagger的第一种使用方式里面,我们得自己为需要注入的类编写Component类;但在这,就不需要这样做了,只需要用@ContributesAndroidInjector标识方法(这个方法必须是抽象的;返回类型必须是Android framework type(Activity、Fragment、Service等),也就是需要注入的类;不能带有方法参数)就行。如果不清楚@ActivityScope的作用,可以看我上篇的博客。我们来看一个编译后,的ActivityBindingModule中的searchActivity()
自动生成的代码。
@Module(subcomponents = ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.class)
public abstract class ActivityBindingModule_SearchActivity {
private ActivityBindingModule_SearchActivity() {}
@Binds
@IntoMap
@ActivityKey(SearchActivity.class)
abstract AndroidInjector.Factory extends Activity> bindAndroidInjectorFactory(
SearchActivitySubcomponent.Builder builder);
@Subcomponent
@ActivityScope
public interface SearchActivitySubcomponent extends AndroidInjector<SearchActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder {}
}
}
@Binds:将AndroidInjector.Factory绑定到SearchActivitySubcomponent.Builder;我的个人理解是Dagger2的代码生成器在编译的时候会将SearchActivitySubcomponent.Builder类型视为AndroidInjector.Factory来处理,其实SearchActivitySubcomponent.Builder本身就是AndroidInjector.Factory的子类。
@IntoMap:用了该注解的方法,其返回类型形成了一个Map
值的类型参数。在这里K就是@ActivityKey的value,也就是SearchActivity.class;V就是方法的返回参数。
如果感兴趣,可以看一下dagger2的多重集合如何使用的官方文档。
bindAndroidInjectorFactory()有什么用呢?这个在后面的代码分析的时候说明
到这,依赖注入的配置工作就完成了。编译工程后,就可以使用了。
第三步、让工程中需要注入的类继承于jar对应的类;比如Activity继承DaggerAppCompatActivity或DaggerActivity,Fragment继承DaggerFragment等
第四步、让工程中编写的Application类继承DaggerApplication(在dagger.android和dagger.android.support包里都有这个类,选那个根据自己的工程决定吧),重写applicationInjector();
@Override
protected AndroidInjector extends DaggerApplication> applicationInjector() {
return DaggerApplicationComponent.builder().application(this).build();
}
applicationInjector()返回的是AndroidInjector extends DaggerApplication>
;这就是我们在编写ApplicationComponent时,要求泛型T必须是注入页面的原因。
到这,我们就完成了。每当有需要注入的类的时候,就只需在ActivityBindingModule类中,再写一个抽象方法就行了;是不是比dagger的第一种方式简便不少。
Google Dagger2Demo
DaggerApplicationComponent做了些什么工作
依赖注入是怎么完成的
我们跟着程序流程,来看看依赖注入怎么完成的。首先看一下MyMovieApplication类源码:
public class MyMovieApplication extends DaggerApplication {
public static MyMovieApplication get(Context context){
return (MyMovieApplication) context.getApplicationContext();
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
protected AndroidInjector extends DaggerApplication> applicationInjector() {
return DaggerApplicationComponent.builder().application(this).build();
}
}
点开DaggerApplication类:
public abstract class DaggerApplication extends dagger.android.DaggerApplication
implements HasSupportFragmentInjector {
@Inject DispatchingAndroidInjector supportFragmentInjector;
@Override
protected abstract AndroidInjector extends DaggerApplication> applicationInjector();
@Override
public DispatchingAndroidInjector supportFragmentInjector() {
return supportFragmentInjector;
}
}
声明supportFragmentInjector变量的时候,用到了@Inject注解。点开DispatchingAndroidInjector类
@Inject
DispatchingAndroidInjector(
Map, Provider>> injectorFactories) {
this.injectorFactories = injectorFactories;
}
前面提到的AndroidSupportInjectionModule类和AndroidSupportInjectionModule类就在这发挥了作用。
DaggerApplication又继承于dagger.android.DaggerApplication,我们再点进去看看:
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();
}
..............
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;
}
.........
}
在onCreate()中调用了applicationInjector.inject(this)
;applicationInjector()
又在MyMovieApplication类中被重写了。
DaggerApplicationComponent.builder().application(this).build();
点开DaggerApplicationComponent类,找到builder()
;
public static ApplicationComponent.Builder builder() {
return new Builder();
}
private static final class Builder implements ApplicationComponent.Builder {
private ApplicationModule applicationModule;
private Application application;
@Override
public ApplicationComponent build() {
if (applicationModule == null) {
this.applicationModule = new ApplicationModule();
}
if (application == null) {
throw new IllegalStateException(Application.class.getCanonicalName() + " must be set");
}
return new DaggerApplicationComponent(this);
}
@Override
public Builder application(Application application) {
this.application = Preconditions.checkNotNull(application);
return this;
}
}
调用build()
,就生成了一个DaggerApplicationComponent实例。
private DaggerApplicationComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
private void initialize(final Builder builder) {
this.mainActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
ActivityBindingModule_MainActivity.MainActivitySubcomponent.Builder>() {
@Override
public ActivityBindingModule_MainActivity.MainActivitySubcomponent.Builder get() {
return new MainActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider = (Provider) mainActivitySubcomponentBuilderProvider;
this.filmmakerActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
ActivityBindingModule_FilmmakerActivity.FilmmakerActivitySubcomponent.Builder>() {
@Override
public ActivityBindingModule_FilmmakerActivity.FilmmakerActivitySubcomponent.Builder
get() {
return new FilmmakerActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider2 =
(Provider) filmmakerActivitySubcomponentBuilderProvider;
this.movieActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
ActivityBindingModule_MovieActivity.MovieActivitySubcomponent.Builder>() {
@Override
public ActivityBindingModule_MovieActivity.MovieActivitySubcomponent.Builder get() {
return new MovieActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider3 = (Provider) movieActivitySubcomponentBuilderProvider;
this.searchActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.Builder>() {
@Override
public ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.Builder get() {
return new SearchActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider4 = (Provider) searchActivitySubcomponentBuilderProvider;
this.sortActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
ActivityBindingModule_SortActivity.SortActivitySubcomponent.Builder>() {
@Override
public ActivityBindingModule_SortActivity.SortActivitySubcomponent.Builder get() {
return new SortActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider5 = (Provider) sortActivitySubcomponentBuilderProvider;
this.mapOfClassOfAndProviderOfFactoryOfProvider =
MapProviderFactory
., AndroidInjector.Factory extends Activity>>builder(5)
.put(MainActivity.class, bindAndroidInjectorFactoryProvider)
.put(FilmmakerActivity.class, bindAndroidInjectorFactoryProvider2)
.put(MovieActivity.class, bindAndroidInjectorFactoryProvider3)
.put(SearchActivity.class, bindAndroidInjectorFactoryProvider4)
.put(SortActivity.class, bindAndroidInjectorFactoryProvider5)
.build();
this.dispatchingAndroidInjectorProvider =
DispatchingAndroidInjector_Factory.create(mapOfClassOfAndProviderOfFactoryOfProvider);
this.dispatchingAndroidInjectorProvider2 =
DispatchingAndroidInjector_Factory.create(
MapProviderFactory
.,
AndroidInjector.Factory extends BroadcastReceiver>>
empty());
this.dispatchingAndroidInjectorProvider3 =
DispatchingAndroidInjector_Factory.create(
MapProviderFactory
., AndroidInjector.Factory extends Fragment>>empty());
this.dispatchingAndroidInjectorProvider4 =
DispatchingAndroidInjector_Factory.create(
MapProviderFactory
., AndroidInjector.Factory extends Service>>empty());
this.dispatchingAndroidInjectorProvider5 =
DispatchingAndroidInjector_Factory.create(
MapProviderFactory
.,
AndroidInjector.Factory extends ContentProvider>>
empty());
this.dispatchingAndroidInjectorProvider6 =
DispatchingAndroidInjector_Factory.create(
MapProviderFactory
.,
AndroidInjector.Factory extends android.support.v4.app.Fragment>>
empty());
this.myMovieApplicationMembersInjector =
MyMovieApplication_MembersInjector.create(
dispatchingAndroidInjectorProvider,
dispatchingAndroidInjectorProvider2,
dispatchingAndroidInjectorProvider3,
dispatchingAndroidInjectorProvider4,
dispatchingAndroidInjectorProvider5,
dispatchingAndroidInjectorProvider6);
this.provideRequestProvider =
DoubleCheck.provider(
ApplicationModule_ProvideRequestFactory.create(builder.applicationModule));
this.dataManagerProvider =
DoubleCheck.provider(
DataManager_Factory.create(
provideRequestProvider,
ImageManagerService_Factory.create(),
LocationManagerService_Factory.create()));
}
在initialize()
中,对成员变量进行赋值。我们以成员变量searchActivitySubcomponentBuilderProvider为例:
this.searchActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.Builder>() {
@Override
public ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.Builder get() {
return new SearchActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider4 = (Provider) searchActivitySubcomponentBuilderProvider;
赋值了一个Factory类(Provider与Factory的关系),其get()
返回SearchActivitySubcomponentBuilder类型
private final class SearchActivitySubcomponentBuilder
extends ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.Builder {
private SearchActivity seedInstance;
@Override
public ActivityBindingModule_SearchActivity.SearchActivitySubcomponent build() {
if (seedInstance == null) {
throw new IllegalStateException(SearchActivity.class.getCanonicalName() + " must be set");
}
return new SearchActivitySubcomponentImpl(this);
}
@Override
public void seedInstance(SearchActivity arg0) {
this.seedInstance = Preconditions.checkNotNull(arg0);
}
}
SearchActivitySubcomponentBuilder继承于
ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.Builder。是不是很熟悉,这个类就是因ActivityBindingModule类的searchActivity()
而自动生成的,其作用就是用来生成SearchActivity对应的Component;调用build()
,就会返回SearchActivitySubcomponentImpl实例。SearchActivitySubcomponentImpl类就是SearchActiivity对应的Component。也就是说searchActivitySubcomponentBuilderProvider就是用来生成SearchActiivity对应Component的工厂
之后,searchActivitySubcomponentBuilderProvider又被赋给bindAndroidInjectorFactoryProvider4变量;bindAndroidInjectorFactoryProvider4又被放入Map中,其key就是SearchActivity.class
this.mapOfClassOfAndProviderOfFactoryOfProvider =
MapProviderFactory
., AndroidInjector.Factory extends Activity>>builder(5)
.put(MainActivity.class, bindAndroidInjectorFactoryProvider)
.put(FilmmakerActivity.class, bindAndroidInjectorFactoryProvider2)
.put(MovieActivity.class, bindAndroidInjectorFactoryProvider3)
.put(SearchActivity.class, bindAndroidInjectorFactoryProvider4)
.put(SortActivity.class, bindAndroidInjectorFactoryProvider5)
.build();
这个Map就是用来存放注入页面对应的工厂;会不会有疑问,为什么dagger2代码生成器会知道bindAndroidInjectorFactoryProvider4对应的K是SearchActivity.class?上面提到过ActivityBindingModule_SearchActivity类中bindAndroidInjectorFactory()有什么用,它的作用就是在这发挥的吧(我也不是很确定)。
private Provider> dispatchingAndroidInjectorProvider;
this.dispatchingAndroidInjectorProvider =
DispatchingAndroidInjector_Factory.create(mapOfClassOfAndProviderOfFactoryOfProvider);
把mapOfClassOfAndProviderOfFactoryOfProvider又传给dispatchingAndroidInjectorProvider;
this.myMovieApplicationMembersInjector =
MyMovieApplication_MembersInjector.create(
dispatchingAndroidInjectorProvider,
dispatchingAndroidInjectorProvider2,
dispatchingAndroidInjectorProvider3,
dispatchingAndroidInjectorProvider4,
dispatchingAndroidInjectorProvider5,
dispatchingAndroidInjectorProvider6);
dispatchingAndroidInjectorProvider又传入myMovieApplicationMembersInjector中;这有什么用呢?
@Override
public void inject(MyMovieApplication arg0) {
myMovieApplicationMembersInjector.injectMembers(arg0);
}
上面提的applicationInjector.inject(this)
,其实就是myMovieApplicationMembersInjector.injectMembers(arg0)
;点进去看
@Override
public void injectMembers(MyMovieApplication instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
dagger.android.DaggerApplication_MembersInjector.injectActivityInjector(
instance, activityInjectorProvider);
dagger.android.DaggerApplication_MembersInjector.injectBroadcastReceiverInjector(
instance, broadcastReceiverInjectorProvider);
dagger.android.DaggerApplication_MembersInjector.injectFragmentInjector(
instance, fragmentInjectorProvider);
dagger.android.DaggerApplication_MembersInjector.injectServiceInjector(
instance, serviceInjectorProvider);
dagger.android.DaggerApplication_MembersInjector.injectContentProviderInjector(
instance, contentProviderInjectorProvider);
dagger.android.DaggerApplication_MembersInjector.injectSetInjected(instance);
dagger.android.support.DaggerApplication_MembersInjector.injectSupportFragmentInjector(
instance, supportFragmentInjectorProvider);
}
打开injectActivityInjector()
;
public static void injectActivityInjector(
DaggerApplication instance,
Provider> activityInjectorProvider) {
instance.activityInjector = activityInjectorProvider.get();
}
这个方法将从DaggerApplicationComponent传入的dispatchingAndroidInjectorProvider赋值给DaggerApplication类中的变量activityInjector。
相比dagger的第一种使用方式中的DaggerApplicationComponent,除了提供一些依赖类需要的实例外;第二种使用方式中的DaggerApplicationComponent还有一个工作,就是将相同类型(这指的是大家都是Activity或Fragment)注入页面的对应工厂收集起来,然后再赋给DaggerApplication类中对应的变量。在DaggerApplicationComponent中并没有对各个注入类的依赖类进行实例化,实例化工作是交给了各个注入类对应的工厂来完成。当我们点进某个注入页面时,工厂才开始实例化工作;也就是说DaggerApplicationComponent保存的是还没开工的工厂。所以,dagger的第二种使用方式在内存上的占用要比基类里统一处理的方式小得多。
接着我们以SearchActivity为例,来看看依赖注入是怎么完成。
SearchActivity继承于DaggerAppCompatActivity,点开DaggerAppCompatActivity类文件
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
在onCreate()
中,调用了AndroidInjection.inject(this)
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().getCanonicalName());
activityInjector.inject(activity);
}
((HasActivityInjector) application).activityInjector()
返回就是DaggerApplication类中的activityInjector变量,也就是DaggerApplicationComponent中的dispatchingAndroidInjectorProvider变量。
AndroidInjector是一个接口,DispatchingAndroidInjector实现了它。
DispatchingAndroidInjector activityInjector;
public final class DispatchingAndroidInjector<T> implements AndroidInjector<T>
DispatchingAndroidInjector重写的inject()
public void inject(T instance) {
boolean wasInjected = maybeInject(instance);
if (!wasInjected) {
throw new IllegalArgumentException(errorMessageSuggestions(instance));
}
}
点进maybeInject()
public boolean maybeInject(T instance) {
Provider> factoryProvider =
injectorFactories.get(instance.getClass());
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().getCanonicalName());
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);
}
}
根据类名查找对应工厂,找到之后就开始工作了。
AndroidInjector injector =
checkNotNull(
factory.create(instance),
"%s.create(I) should not return null.",
factory.getClass().getCanonicalName());
factory.create(instance)
;要想找到create()
;首先,我们要搞清楚factory的类型是什么?其实就是SearchActivitySubcomponentBuilder,其继承于ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.Builder,ActivityBindingModule_SearchActivity.SearchActivitySubcomponent.Builder继承于AndroidInjector.Builder
abstract class Builder implements AndroidInjector.Factory {
@Override
public final AndroidInjector create(T instance) {
seedInstance(instance);
return build();
}
/**
* Provides {@code instance} to be used in the binding graph of the built {@link
* AndroidInjector}. By default, this is used as a {@link BindsInstance} method, but it may be
* overridden to provide any modules which need a reference to the activity.
*
* This should be the same instance that will be passed to {@link #inject(Object)}.
*/
@BindsInstance
public abstract void seedInstance(T instance);
/** Returns a newly-constructed {@link AndroidInjector}. */
public abstract AndroidInjector build();
}
是不是找到了create()
,方法中又调用了build()
;这调用的就是SearchActivitySubcomponentBuilder中build()
方法,返回SearchActivitySubcomponentImpl实例;上面的injector变量就是SearchActivitySubcomponentImpl实例。
private final class SearchActivitySubcomponentImpl
implements ActivityBindingModule_SearchActivity.SearchActivitySubcomponent {
private Provider searchMvpPresenterProvider;
private Provider movieRecyclerViewAdapterProvider;
private MembersInjector searchActivityMembersInjector;
private SearchActivitySubcomponentImpl(SearchActivitySubcomponentBuilder builder) {
assert builder != null;
initialize(builder);
}
@SuppressWarnings("unchecked")
private void initialize(final SearchActivitySubcomponentBuilder builder) {
this.searchMvpPresenterProvider =
SearchMvpPresenter_Factory.create(
MembersInjectors.noOp(),
DaggerApplicationComponent.this.dataManagerProvider);
this.movieRecyclerViewAdapterProvider =
MovieRecyclerViewAdapter_Factory.create(
MembersInjectors.noOp(),
DaggerApplicationComponent.this.dataManagerProvider);
this.searchActivityMembersInjector =
SearchActivity_MembersInjector.create(
DaggerApplicationComponent.this.dispatchingAndroidInjectorProvider6,
DaggerApplicationComponent.this.dispatchingAndroidInjectorProvider3,
searchMvpPresenterProvider,
movieRecyclerViewAdapterProvider);
}
@Override
public void inject(SearchActivity arg0) {
searchActivityMembersInjector.injectMembers(arg0);
}
}
SearchActivitySubcomponentImpl中有三个成员变量,在initialize(builder)
中进行初始化。在上面的maybeInject()
中执行的injector.inject(instance)
,实际就是SearchActivitySubcomponentImpl类中的inject(SearchActivity arg0)
方法,其方法又调用了searchActivityMembersInjector.injectMembers(arg0)
。点进injectMembers(arg0)
看看:
@Override
public void injectMembers(SearchActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
dagger.android.support.DaggerAppCompatActivity_MembersInjector.injectSupportFragmentInjector(
instance, supportFragmentInjectorProvider);
dagger.android.support.DaggerAppCompatActivity_MembersInjector.injectFrameworkFragmentInjector(
instance, frameworkFragmentInjectorProvider);
instance.mSearchMvpPresenter = mSearchMvpPresenterProvider.get();
instance.mMovieRecyclerViewAdapter = mMovieRecyclerViewAdapterProvider.get();
}
是不是发现了,SearchActivity中的两个变量就赋值完成,依赖注入工作就完成了。
相比dagger的第一种使用方式中,在基类中统一处理的方式,要好很多。首先,各个注入类都有对应的Component;其次,在Component中不会有多余的成员变量,也就是说,不会浪费内存。