1. 程式人生 > >android開源庫---Dagger2入門學習(簡單使用)

android開源庫---Dagger2入門學習(簡單使用)

Dagger2依賴注入

前面我們做好學習準備接下來就要研究如何使用了,俗話說的好,一個東西需要先會用,然後才更好的學習原理。

一、匯入Dagger2

在工程的build.gradle檔案中新增android-apt外掛(該外掛後面介紹)

buildscript {

    ....

    dependencies {

        classpath 'com.android.tools.build:gradle:2.1.0'
        // 新增android-apt 外掛
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
} }

在app的中的build.gradle檔案中新增配置

apply plugin: 'com.android.application'
// 應用外掛
apply plugin: 'com.neenbedankt.android-apt'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.mahao.alex.architecture"
        minSdkVersion 15
        targetSdkVersion 23
versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar'
]) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.3.0' // dagger 2 的配置 compile 'com.google.dagger:dagger:2.4' apt 'com.google.dagger:dagger-compiler:2.4' compile 'org.glassfish:javax.annotation:10.0-b28'// 新增java 註解庫 }

android-apt是Gradle編譯器的外掛,根據其官方文件,主要兩個目的:

  • 編譯時使用該工具,最終打包時不會將該外掛打入到apk中。
  • 能夠根據設定的源路徑,在編譯時期生成相應程式碼。

二、寫個Demo

這個就依照上篇的女孩依賴於一個男孩,這我們再加一個依賴就是父母(畢竟男人不一定靠的住^(* ̄(oo) ̄)^)。好了開始寫
寫一個Module類,管理上面的依賴。

@Module
public class GirlModule {
    @Provides
    public Boy provideBoy(){
        return new Boy();
    }

    @Provides
    public Parents provideParents(){
        return new Parents();
    }

}

寫一個Component類,來連線Module和你的Girl。

@Component(modules = GirlModule.class)
public interface GirlComponent {
    void inject(Girl girl);
}

到了這裡不要急著往下寫,先執行一下你的程式碼。(下面再說為什麼)

好了,繼續下一步,重寫Girl類

public class Girl {
    @Inject
    Boy boy;
    @Inject
    Parents parents;
    public Girl() {
        DaggerGirlComponent
                .builder()
                .girlModule(new GirlModule())
                .build()
                .inject(this);
        Log.d("Girl", "new Girl()");

    }

}

首先我們可以看到在使用過程出現了很多註解:

  • @Module:作為例項物件的容器。
  • @Provides:標註能夠提供例項化物件的方法。
  • @Component:作為橋樑,注入物件的通道。
  • @Inject:需要注入的方法

分析

我們可以看到在GirlModule 是用一個@Module註解的類,這是作為例項物件的容器,用於管理,裡面的方法是使用@Provides註解,可以看出來其實就是給你提供依賴的方法。
我們知道了管理並提供依賴的類,那麼我們就可以通過它來直接使用依賴。但是Dagger2為了解耦,提供了一箇中介,@Component註解,這是作為橋樑將依賴和需求(girl)聯絡起來。


@Component(modules = GirlModule.class)
public interface GirlComponent {
    void inject(Girl girl);
}

那麼我們來看看@Component的官方文件。

* Annotates an interface or abstract class for which a fully-formed,     dependency-injected
 * implementation is to be generated from a set of {@linkplain #modules}.

說的是這個註解只能用於介面或者抽象類。將程式碼改成下面,輸出也是一樣的。

@Component(modules = GirlModule.class)
public abstract GirlComponent {
    void inject(Girl girl);
}

還有 @Inject註解 就是使用的時候的注入方法。

 @Inject
    Boy boy;

上面的程式碼表示Boy 這個屬性你不用像一般情況去初始化(boy= new Boy ()),它能給你自動尋找依賴。
但是這樣就可以了麼?當然是不行,你都沒有和前面的聯絡其來。所以還需要如下程式碼:

DaggerGirlComponent
                .builder()
                .girlModule(new GirlModule())
                .build()
                .inject(this);

這裡你就會看到一個你沒有建立的類是,這個是由apt工具幫我們生成的類,但是是在編譯時期生成程式碼,所以為什麼前面要你們先執行下(我之前就是一頭霧水,大部分人都說生成沒說怎麼生成,搞的我一度誤解)

這裡tip一下

在android-apt的文件中,也推薦使用這種方式。因為,編譯時期生成程式碼的類庫在執行期並不需要,那麼將其分為兩個庫,(執行類庫dagger)和(編譯器生成程式碼類庫(dagger-compiler)),那麼在打包時,就不需要將dagger-compiler打入其中(用不到),減小APK 的大小。

DaggerGirlComponent實現了GirlComponent介面。
通過girlModule()將我們的依賴提供者傳入,通過inject()將我們的Girl物件傳入,這樣就達到了中間人的目的。

package com.example.admin.dagger2.gg;

import dagger.MembersInjector;
import dagger.internal.Preconditions;
import javax.annotation.Generated;
import javax.inject.Provider;

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerGirlComponent implements GirlComponent {
  private Provider<Boy> provideBoyProvider;

  private Provider<Parents> provideParentsProvider;

  private MembersInjector<Girl> girlMembersInjector;

  private DaggerGirlComponent(Builder builder) {
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {
    return new Builder();
  }

  public static GirlComponent create() {
    return builder().build();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.provideBoyProvider = GirlModule_ProvideBoyFactory.create(builder.girlModule);

    this.provideParentsProvider = GirlModule_ProvideParentsFactory.create(builder.girlModule);

    this.girlMembersInjector =
        Girl_MembersInjector.create(provideBoyProvider, provideParentsProvider);
  }

  @Override
  public void inject(Girl girl) {
    girlMembersInjector.injectMembers(girl);
  }

  public static final class Builder {
    private GirlModule girlModule;

    private Builder() {}

    public GirlComponent build() {
      if (girlModule == null) {
        this.girlModule = new GirlModule();
      }
      return new DaggerGirlComponent(this);
    }

    public Builder girlModule(GirlModule girlModule) {
      this.girlModule = Preconditions.checkNotNull(girlModule);
      return this;
    }
  }
}

到這裡基本的入門使用就知道。
這裡想必還是一頭霧水感覺不出有什麼用處,不要著急,飯要一口一口吃,我們先了解使用,然後再慢慢一步一步瞭解。