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的學習筆記我會在接下來的博客繼續更新。





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