前言
依赖注入是我在安卓项目架构学习(dagger+mvp+retrofit+rxjava+eventbus)里面的又一大步。通过一天多的系统学习(看别人的项目源码,博客文章,自己看dagger的生成源码),差不多也可以去自己总结一下了。dagger2的用法网上太多教程了,我就不再描述了。这里我只总结依赖注入的概念,在项目架构中的作用以及部分最基础的生成源码个人分析。建议大家在学习dagger之前先去学习java注解和反射,因为dagger确实不好理解,如果有了注解基础学习起来会更轻松。
以前看人家大牛的项目都有个inject包,以前想当然的以为就是个注解包。。也不懂里面的component和module包是干嘛的。现在想想,也又算一种进步吧!
大家可以通过我这个练手app巩固dagger的用法 :githubQuery
依赖注入?(DI and IOC)
其实依赖注入也是为了模块解耦,你会发现一切一切,不论是mvp还是dagger都是为了模块解耦。dagger和mvp结合起来还可以做到把m-v-p之间进一步解耦。所谓耦合就是两个模块联系在了一起,什么意思呢?比如一个模块A里面new了另一个模块B的对象,这时候就说两个模块耦合在了一起,如果现在B模块的构造函数做了修改,那么你还需要去修改模块A里面的代码。而我们希望的是B无论怎么修改都不会影响模块A。(联系mvp模式,无论m层怎么修改,都不会影响v层)而依赖注入可以用两种方法来解决:
1.传递依赖:
class A{
//...
B b;
public A(B b){
this.b = b;
}
}
或者传递给 B的更高层级的抽象层(面向接口编程的思想)。
2.注入依赖。(如dagger di框架)
其实这种解决办法就叫做控制反转(ioc)。把添加依赖的权利给外部,自己不去主动添加依赖关系
好像有人分不大清楚dagger和butterknife有啥区别。。其实区别很大,butterkinfe也是通过注解来实现依赖注入,不过他做的是view的依赖注入。而dagger做的是更高层次的模块之间的依赖注入。
话说以前还写了一个很简单的view依赖注入框架(用的反射),我记得我以前在github上面写的是依赖注入框架,后来赶紧改成了view依赖注入框架。。
依赖注入器?
如果说用传递依赖的话,那么如果模块A需要模块B的大量对象,或者说依赖程度很高,那么传递函数里面的依赖参数将会很多。
而使用注入器可以极大的减少代码量,模块之间的依赖关系也会很清晰。把注入器看作项目的一个模块(inject)专门负责把某些模块注入到他的依赖中去。当然说这些你可能还是不能体会到它的好处,多去写写,看看人家的项目代码才能慢慢体会。(比如我把所有的基础配置以及application的context全部提供在applicaion的module,然后直接把这个module注入到baseactivity或者application中去,然后其他的activity module再去继承这个application module。一行代码就去注入很多的依赖!)
Dagger2
dagger2就是现在一个比较火的依赖注入器框架。它使用的预编译期间生成代码完成依赖,而不是用的反射。。都知道反射对手机应用开发影响是比较大的。我学习这个框架就把它想成了一个注射器,component是针管,module是注射瓶,里面的依赖对象是注入的药水,build方法是插进患者,inject方法的调用是推动活塞。这样形象的理解还是很容易理解的!!
dagger需要掌握的就是component, module, scope, provides, singleton.
下面来探讨部分生成源码吧。
描述:我现在有两个medule,并且其中一个component依赖另一个component。代码如下
/**
* Created by Zane on 16/1/21.
*/
@Module
public class ActivityModule {
@Provides
UserModel provideUserModel(){
return new UserModel();
}
}
@Module
public class ActivityModule2 {
@Provides
UserModelTwo provideUserModelTwo(){
return new UserModelTwo();
}
}
@Component(modules = ActivityModule.class)
public interface ActivityComponent {
//void inject(Activity activity);
UserModel userModel();
}
@Component(dependencies = ActivityComponent.class, modules = ActivityModule2.class)
public interface ActivityComponent2 {
void inject(MainActivity activity);
}
两个model/bean代码如下:
/**
* Created by Zane on 16/1/21.
*/
public class UserModel {
private String name = "xuzhi";
private String age = "20";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
public class UserModelTwo {
private String phone = "1888";
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
在activity中的注入代码如下:
activityComponent = DaggerActivityComponent
.builder()
.activityModule(new ActivityModule())
.build();
activityComponent2 = DaggerActivityComponent2
.builder()
.activityComponent(activityComponent)
.activityModule2(new ActivityModule2())
.build();
activityComponent2.inject(this);
我们都知道,编译之后dagger框架会自动给我们生成以dagger+xxxcomponent为名的类。如我的代码就是生成了DaggerActivityComponent类,并且通过一系列的方法调用最终构建成功。看过生成代码的人会感觉他用的就是包装器模式!我们首先来看DaggerActivityComponent的builder()方法:
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerActivityComponent implements ActivityComponent {
private Provider provideUserModelProvider;
private DaggerActivityComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
可以看到生成了一个Provider
public static final class Builder {
private ActivityModule activityModule;
private Builder() {
}
public ActivityComponent build() {
if (activityModule == null) {
this.activityModule = new ActivityModule();
}
return new DaggerActivityComponent(this);
}
public Builder activityModule(ActivityModule activityModule) {
if (activityModule == null) {
throw new NullPointerException("activityModule");
}
this.activityModule = activityModule;
return this;
}
}
注入代码中,我们紧接着调用了activityModule(ActivityModule activityModule)方法。我们看到因为在ActivityComponent中我们用@component添加了ActivityModule。所以这里生成了这样一个方法来让你传递一个对象进来。之后我们调用了build()方法,这个方法里面调用了DaggerActivityComponent类的构造方法!
private DaggerActivityComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
这里也没啥看的,继续看initialize(builder);方法:
private void initialize(final Builder builder) {
this.provideUserModelProvider = ActivityModule_ProvideUserModelFactory.create(builder.activityModule);
}
这里有个新类,叫做xxxxFactory,这个类很重要,点进去继续看creat方法:
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class ActivityModule_ProvideUserModelFactory implements Factory {
private final ActivityModule module;
public ActivityModule_ProvideUserModelFactory(ActivityModule module) {
assert module != null;
this.module = module;
}
@Override
public UserModel get() {
UserModel provided = module.provideUserModel();
if (provided == null) {
throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");
}
return provided;
}
public static Factory create(ActivityModule module) {
return new ActivityModule_ProvideUserModelFactory(module);
}
}
很简单,就是把我们的ActivityModule存在了这个类里面,并提供一个get方法,这个get方法之后会用到。
DaggerActivityComponent类的代码我们就看完了,很简单,因为这个针头并没有提供inject方法哈哈,而是多重依赖给了ActivityComponent2.接下来看DaggerActivityComponent2的代码:
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerActivityComponent2 implements ActivityComponent2 {
private Provider userModelProvider;
private Provider provideUserModelTwoProvider;
private MembersInjector mainActivityMembersInjector;
private DaggerActivityComponent2(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
第一个module中的usermodel也被注入到了第二个module中!接着看Builder类
public static final class Builder {
private ActivityModule2 activityModule2;
private ActivityComponent activityComponent;
private Builder() {
}
public ActivityComponent2 build() {
if (activityModule2 == null) {
this.activityModule2 = new ActivityModule2();
}
if (activityComponent == null) {
throw new IllegalStateException("activityComponent must be set");
}
return new DaggerActivityComponent2(this);
}
public Builder activityModule2(ActivityModule2 activityModule2) {
if (activityModule2 == null) {
throw new NullPointerException("activityModule2");
}
this.activityModule2 = activityModule2;
return this;
}
public Builder activityComponent(ActivityComponent activityComponent) {
if (activityComponent == null) {
throw new NullPointerException("activityComponent");
}
this.activityComponent = activityComponent;
return this;
}
}
ActivityModule2 activityModule2,ActivityComponent activityComponent;都是这个类的静态变量,因为一个是依赖一个是对应的 module。然后你可以自己看看注入代码,我们确实是分别调用了activityComponent(ActivityComponent activityComponent),activityModule2(ActivityModule2 activityModule2)之后才去调用build();
private void initialize(final Builder builder) {
this.userModelProvider = new Factory() {
private final ActivityComponent activityComponent = builder.activityComponent;
@Override public UserModel get() {
UserModel provided = activityComponent.userModel();
if (provided == null) {
throw new NullPointerException("Cannot return null from a non-@Nullable component method");
}
return provided;
}
};
this.provideUserModelTwoProvider = ActivityModule2_ProvideUserModelTwoFactory.create(builder.activityModule2);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), userModelProvider, provideUserModelTwoProvider);
}
最上面有一段代码,其用意相当于重新构建一个xxxxFactory类。你可以看到之前那个xxxFactory类是实现了Factory
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class MainActivity_MembersInjector implements MembersInjector {
private final MembersInjector supertypeInjector;
private final Provider modelProvider;
private final Provider model2Provider;
public MainActivity_MembersInjector(MembersInjector supertypeInjector, Provider modelProvider, Provider model2Provider) {
assert supertypeInjector != null;
this.supertypeInjector = supertypeInjector;
assert modelProvider != null;
this.modelProvider = modelProvider;
assert model2Provider != null;
this.model2Provider = model2Provider;
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
supertypeInjector.injectMembers(instance);
instance.model = modelProvider.get();
instance.model2 = model2Provider.get();
}
public static MembersInjector create(MembersInjector supertypeInjector, Provider modelProvider, Provider model2Provider) {
return new MainActivity_MembersInjector(supertypeInjector, modelProvider, model2Provider);
}
}
很清楚了,也是一种包装器模式。我们可以类比,每一个被注入的类都会生成一个xxx_MembersInject类。看到我们把两个Factory对象都传进来了,并且调用了get方法来获得我们需要注入的依赖对象。大功告成,最后看DaggerActivityComponent2里面的最后一个方法:
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
对!就是我们MainActivity里面调用的inject()方法。对应上一份源码看,懂了吧!这就是注入过程,所以我把inject()方法的调用比做活塞的推动。
所以看了这么多,其实就是想多了解一下dagger如何运作,我们的调用代码tmd为什么要这么写。嗯,就是这样!之前学这个也是越看越烦啦,后来慢慢的总结一下也是极好的。下面就准备开始用mvp+dagger2+rxjava+retrofit来搞点事情了。并且我还不准备用我自己的mvp框架,感觉写的太渣了,分分钟爆炸的节奏。。
未经博主同意,不得转载该篇文章