Dagger2的学习笔记 · 一

今天玩一下Dagger2,个人第一感觉就是,一种本来挺好理解的东西,硬生生被玩着复杂和变得难以理解了,哈哈,也有可能是自己技术水平不够,不说废话了,下面开始记录一下我的学习心得。

Dagger2,官方的说明是A fast dependency injector for Android and Java,翻译成国语就是“Android和Java的快速依赖注入器。”

一、什么是依赖注入

下面先看一个例子,比如我假设有一个类——Ferry(船),一个类——Paddle(桨),现在我们需要定义一个船类,并且在船类中定义一个变量桨类,我们会这样做:

class Ferry{
    Paddle paddle = new Paddle();
    Ferry();
}

上面这种写法很完美的解决问题,但是现在如果Ferry类的需求改了,需要加入一个参数,那么我们是不是要同时修改Ferry类和Paddle类,这样看来Ferry类是不是很依赖Paddle类,Paddle类一改,Ferry类就要跟改。那么我们的程序员就想出一个方法,不在Ferry类中新建Paddle类,而是在外面把Paddle类注入进入,比如这样:

class Ferry{
    Paddle paddle;
    Ferry(Paddle paddle){
        this.paddle = paddle;
    }
}

上面这这种做法就是依赖注入把所依赖的Paddle类从外面把它注入进来,而不是在Ferry类中自己建立。而Dagger2就是用来做上面依赖注入这一步的,他的基本原理就是这么简单,但是跟上面不同,他不是直接以构造方法的参数形式注入的,下面我会详细解释。

补充一下:依赖注入其实是一种方法,他的主要思想叫做控制反转(Inversion of Control,英文缩写为IoC),控制反转还有另一种方法叫做依赖查找,想了解详细的,自行百度。

二、环境搭建

怎么将Dagger2接入AS工程中,只需要两步:

1、在主工程下的build.gradle中加入classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'


2、然后在app模块分别加入:

apply plugin: 'com.neenbedankt.android-apt'


compile ‘com.google.dagger:dagger:2.11’

apt‘com.google.dagger:dagger-compile:2.11’

provided ‘org.glassfish:javax.annotation:10.0-b28’


这样就完成Dagger2的Gradle配置,如果你是高版本的AS这样配置可能会出现问题,请参考我的另一篇博客

http://blog.csdn.net/m0_37605407/article/details/79091389

三、现在开始玩最简单的Dagger2

下面这些步骤都是基本固定,只要按照这样的步骤就可以实现Dagger2构架的接入。

我们接着上面船和桨的例子,用Dagger2实现依赖注入:

//船类
public class Paddle {
    @Override
    public String toString() {
        return "我是船";
    }
}
//Paddle的提供类
@Module
public class MainModule {

    @Provides
    public Paddle getPaddle() {
        Paddle paddle = new Paddle();
        return paddle;
    }
}
//建立一个接口,连接Paddle类和Ferry类的关系
@Component(modules=MainModule.class)
public interface MainComponent {
    void inject(FerryActivity ferryActivity);
}

然后编译,你会惊喜发现自动多了两个中间类。


现在可以在Ferry类中进行依赖注入了

public class FerryActivity extends AppCompatActivity {

    @Inject
    Paddle paddle;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MainComponent build = DaggerMainComponent.builder().mainModule(new MainModule()).build();    //关键代码1
        build.inject(this);            //关键代码2
        Log.d("Dagger2",paddle.toString() );
    }
}

到这里就完成了整个步骤,可以成功打印出     03-21 23:18:18.918 28286-28286/? D/Dagger2: 我是船

我们开始从代码中去看Dagger2到底干些什么?

首先,在FerryActivity中调用关键代码1,新建了DaggerMainComponent类中的静态内部类Builder,然后把一个新建MainModule类传递给Builder,最后新建一个带有MainModule对象的DaggerMainComponent类

public static final class Builder {
    private MainModule mainModule;

    private Builder() {}

    public MainComponent build() {
      if (mainModule == null) {
        this.mainModule = new MainModule();
      }
      return new DaggerMainComponent(this);//新建一个带有MainModule对象的DaggerMainComponent类
    }

    public Builder mainModule(MainModule mainModule) {
      this.mainModule = Preconditions.checkNotNull(mainModule);//FerryActvity调用这个方法传递进去MainModule对象
      return this;
    }
  }

然后,在DaggerMainComponent类的构造方法中

private DaggerMainComponent(Builder builder) {
    assert builder != null;
    initialize(builder);//在这步里面做了关键步骤
  }
private void initialize(final Builder builder) {

    this.getPaddleProvider = MainModule_GetPaddleFactory.create(builder.mainModule);

    this.ferryActivityMembersInjector = FerryActivity_MembersInjector.create(getPaddleProvider);
  }

我们先来看,this.getPaddleProvider = MainModule_GetPaddleFactory.create(builder.mainModule)这一步干了些什么?

public static Factory<Paddle> create(MainModule module) {
    return new MainModule_GetPaddleFactory(module);
  }

上面代码中,新建了MainModule_GetPaddleFactory对象,然后传递给了FerryActivity_MembersInjector的静态方法create。

public static MembersInjector<FerryActivity> create(Provider<Paddle> paddleProvider) {
    return new FerryActivity_MembersInjector(paddleProvider);
  }
上面代码中,新建了一个带有MainModule_GetPaddleFactory对象的FerryActivity_MembersInjector类。
然后在FerryActivity中调用了关键代码2

调用了DaggerMainComponent类中的inject方法

 @Override
  public void inject(FerryActivity ferryActivity) {
    ferryActivityMembersInjector.injectMembers(ferryActivity);
  }
public void injectMembers(FerryActivity instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.paddle = paddleProvider.get();
  }
public Paddle get() {
    return Preconditions.checkNotNull(
        module.getPaddle(), "Cannot return null from a non-@Nullable @Provides method");
  }

哈哈,到这里真相大白了,FerryActivity.paddle = Module.getPaddle,其实啊,弄了这么久,Dagger就是做了这么一件事情。

今天先到这里,上面的出现的一些注解,只是为了让apt编译出中间的类,但是对于这些注解的特殊用法,我还没有去深究,关于Dagger2的学习笔记我会在接下来的博客继续更新。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章