本文适合接触过,或者已经使用了一段dagger2的小伙伴加深印象,或者想要深入的了解关于dagger2如何进入DI(dependencies inject)过程的一个简单的分析,起到抛砖引玉的作用.
如果你还不知道Dagger2是什么的话,建议去Google 百度 一下.这里就不赘述了,好多好多资料..
- Provider
- Factory
- MembersInjector
前两个接口其实是一个东西. Factory 继承了 Provider 内部只存在1个方法 get();究其根本,从字面意思上理解就是提供者.它们是泛型借口,get()方法的返回值也同样是该泛型.这里我们可以做一下猜测,它返回的应该是需要注入的类.
MembersInjector 同样也是一个接口,内部也是只有一个方法
injectMembers(T instance) 很直白,直面理解就是成员注入,猜测这个的作用是对于目标累的注入,而T则是目标类.
编译生成的累并不多.
为了防止迷惑.下面讲简单的贴出dagger2的配置过程,如果小伙伴们对这个配置已经很熟悉的话请忽略下面,直接跳到分析原理的过程
AppComponent
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
Context getContext();
}
AppModule
@Module
public class AppModule {
private Application appContext;
public AppModule(App app) {
this.appContext = app;
}
@Provides
@Singleton
public Context provideContext() {
return appContext;
}
}
App
public class App extends Application {
private static App INSTANCE;
@Override
public void onCreate() {
super.onCreate();
INSTANCE = this;
}
public static AppComponent getAppComponent() {
AppComponent appComponent = DaggerAppComponent.builder()
.appModule(new AppModule(INSTANCE))
.build();
return appComponent;
}
}
ActivityComponent
@ActivityScope
@Component(dependencies = AppComponent.class,modules = ActivityModule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
ActivityModule
@Module
public class ActivityModule {
private Activity activity;
public ActivityModule(Activity activity) {
this.activity = activity;
}
@Provides
@ActivityScope
public Context provideContext() {
return activity;
}
@Provides
@ActivityScope
public Person providePerson() {
return new Person();
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
@Inject Person p;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
injectActivity();
initView();
}
private void injectActivity() {
ActivityComponent activityComponent = DaggerActivityComponent
.builder()
.appComponent(App.getAppComponent())
.activityModule(new ActivityModule(this))
.build();
activityComponent.inject(this);
}
private void initView() {
textView =(TextView)findViewById(R.id.tv_daggertest);
textView.setText(p.toString());
}
}
Person
public class Person {
private String name = "张三";
private int age = 26;
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
好了.下面开始步入正题,证实我们上面的猜测.这里我们直接从Activity的注入开始.因为App种并不需要注入.只需要提供AppComponent
public final class DaggerActivityComponent implements ActivityComponent {
private Provider providePersonProvider;
private MembersInjector mainActivityMembersInjector;
private DaggerActivityComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.providePersonProvider =
DoubleCheck.provider(ActivityModule_ProvidePersonFactory.create(builder.activityModule));
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(providePersonProvider);
}
@Override
public void inject(MainActivity mainActivity) {
mainActivityMembersInjector.injectMembers(mainActivity);
}
public static final class Builder {
private ActivityModule activityModule;
private AppComponent appComponent;
private Builder() {}
public ActivityComponent build() {
if (activityModule == null) {
throw new IllegalStateException(ActivityModule.class.getCanonicalName() + " must be set");
}
if (appComponent == null) {
throw new IllegalStateException(AppComponent.class.getCanonicalName() + " must be set");
}
return new DaggerActivityComponent(this);
}
public Builder activityModule(ActivityModule activityModule) {
this.activityModule = Preconditions.checkNotNull(activityModule);
return this;
}
public Builder appComponent(AppComponent appComponent) {
this.appComponent = Preconditions.checkNotNull(appComponent);
return this;
}
}
}
这个类是配置后AS编译后生成的.名称是固定的DaggerActivityComponent就是在自定义的 XXXComponent前面加上Dagger ,其实就是他的实现类,实现了你在Component中定义的所有方法,和通常的接口实现类并没有说明去区别.
在它的内部,IDE帮我们生成了下面2个成员变量
- private Provider
providePersonProvider; - private MembersInjector
mainActivityMembersInjector;
并在构造函数中进行初始化
private void initialize(final Builder builder) {
this.providePersonProvider =
DoubleCheck.provider(ActivityModule_ProvidePersonFactory.create(builder.activityModule));
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(providePersonProvider);
}
在前面也提到了这2个对象的一些作用,一个是提供,一个是注入,
Provider
ActivityModule_ProvidePersonFactory
public final class ActivityModule_ProvidePersonFactory implements Factory<Person> {
private final ActivityModule module;
public ActivityModule_ProvidePersonFactory(ActivityModule module) {
assert module != null;
this.module = module;
}
@Override
public Person get() {
return Preconditions.checkNotNull(
module.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory create(ActivityModule module) {
return new ActivityModule_ProvidePersonFactory(module);
}
}
通过Create方法传递对应提供的配置的module注入到类中,然后在get方法种返回得到的Person实例,其实这里调用的module.providePerson()就是在ActivityModule种用@Provider标识的providePerson()方法
MainActivity_MembersInjector
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider pProvider;
public MainActivity_MembersInjector(Provider pProvider) {
assert pProvider != null;
this.pProvider = pProvider;
}
public static MembersInjector create(Provider pProvider) {
return new MainActivity_MembersInjector(pProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.p = pProvider.get();
}
public static void injectP(MainActivity instance, Provider pProvider) {
instance.p = pProvider.get();
}
}
因为在DaggerActivityCompon的构造函数中ActivityModule_ProvidePersonFactory的实例已经传递到了mainActivityMembersInjector中,也就是说,其实这两个类已经形成了依赖关系,这里
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.p = pProvider.get();
}
这个方法其实就是给Activity种用@Injcet标识的Person对象进行赋值,这个方法其实就是在DaggerActivityComponent中调用的,这样一来,所有的注入关系,初始化关系就形成了.
到这里.dagger2的注入原理就分析完成了,总结一下
IDE帮助我们生成的以Dagger开头的类,实现了我们自定义的XXXComponent,并在构造方法中初始化了Provider和MembersInjector的实现类的实例,并把Provider的实例传入MembersInjector中,形成依赖关系.然后通过Provider的实现类中的get方法获取自定义的Module中配置的实例,在MembersInjector的injectMembers方法中完成对目标类注入依赖类的初始化工作.