用dagger2煮咖啡

配制dagger2開發環境

  • 配制project下的build.gradle
buildscript {  
     repositories {    
         jcenter()   
     }

    dependencies {        
        classpath 'com.android.tools.build:gradle:2.1.0'        
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'            
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files    
    }
}
  • 配制module下的build.gradle
  • 添加apt插件 apply plugin: 'com.neenbedankt.android-apt'
  • 添加dagger依賴
dependencies {
        ...
 
        apt 'com.google.dagger:dagger-compiler:2.5'    
        compile 'com.google.dagger:dagger:2.5'
}

說明:gradle中的依賴分為兩種:一種是gradle自身需要的依賴,另一種是構建工程需要的依賴。
在buildscript下的dependencies結點添加gradle自身需要的依賴,如:

/Dagge2Coffee/build.gradle

直接在dependencies結點下添加構建工程需要的依賴,如:
/Dagge2Coffee/app/build.gradle

apt是由android-apt插件提供的,添加android-apt插件的方法為 apply plugin: 'com.neenbedankt.android-apt' 其中apply plugin是gradle語法,所在包為'com.android.tools.build:gradle:2.1.0'即在buildscript-depenpendencs下classpath 'com.android.tools.build:gradle:2.1.0'引入的。添加android-apt插件后就可以使用apt命令了。apt 'com.google.dagger:dagger-compiler:2.5'的含意是,編譯時使用dagger-compiler,打包時不需要將dagger-compiler包打包到apk中。因為dagger2在編譯時根據注解生成相應代碼,所以在打包時沒有必要將不需要的三方包(dagger-compiler)打包到apk里。

這里說一下dagger-compiler與dagger的區別

  • dagger-compiler.jar有8M左右,dagger.jar有27K左右
  • dagger-compiler.jar是根據注解生成代碼的主體,dagger.jar里基本上只包含工廠類和注解類
  • dagger-compiler.jar在編譯時使用,不需要打包到apk里;dagger.jar提供注解和抽象,需要打包到apk里

根據Dagger1的CoffeeSimple寫一個Dagger2程序

Dagger2有很多注解,而且可以自定義注解。本次任務是用最少的代碼寫出一個最小的程序。用到Module,Provides,Inject,Component,Singleton五個最基本的注解,以下是它們的簡單介紹:

  • Module作用于類上,表明該是一個工廠類,產生各種活生生的類
  • Provides作用于Module中的方法上,表示該方法可以提供一個類
  • Singleton表示提供的類為單列
  • Inject標記需要注入的變量
  • Component作用于接口類上,使該類相當于一個紐帶,連接Module和需要注入實例的類(如:Activity)。就是將Module中生成的類注入(賦值)到Activity中使用Inject標記的變量上

由于CoffeeSimple是基于Dagger1寫的,主要意圖是將CoffeeMaker注入到CoffeeApp的coffeeMaker變量,是一個java程序。我們用Dagger2在android程序上重新演繹一下該過程,所以這個CoffeeApp.java類就沒有用了(用MainActivity.java代替)。看一下CoffeeSimple里的類

/CoffeeSimple/*.java

暫時先不管CoffeeApp,根據名字可以將它們簡單分一下類,其中Heater, ElectricHeater, Pump, Thermosiphon, CoffeeMaker屬于實體類(Model),DripCoffeeModule, PumpModule屬于提供類的工廠(Module)。
簡單建立一個android demo,結構如下:
/Dagge2Coffee/app/src/main/java/rubo/dagge2coffee

接下來逐一介紹上面說到的五個注解在Dagger2Coffee中起到的作用
首先查看實體類的UML類圖,使用plantUML畫的,各類圖位置不好調整湊合著看吧。
model.puml

從圖中可以看出model類中只使用了一個注釋Inject,分別標記了CoffeeMaker里的heater、pump字段、構造器和Thermosiphon的構造器,Inject作用之前已經提到了。
然后查看module的UML類圖,如下

module.puml

這里看不出注解,因為我不知道如何使用plaintUml給類圖添加注解~~ 但是還是可以看出Module就是一個工廠類,只提供生成類的方法。現在進入module類里查看使用了什么注解

//DripCoffeModul.java

@Module
public class DripCoffeeModule {
    @Provides
    @Singleton
    Heater provideHeater() {
            return new ElectricHeater();
    }
}
//PumpModule.java

@Module
public class PumpModule {
        @Provides
        @Singleton
        Pump providePump(Thermosiphon pump) {
            return pump;
        }
}

這里使用了三個注釋,Module、Provides、Singleton 它們各自的作用之前已經提到了。
基本的材料都已經做好了,接下來該使用了。
小插曲,用過ButterKnife的同學都應該知道以下代碼片段的作用


sample

我們如何使用Dagger2達到同樣的效果呢,比如這樣


sample2

直接這樣肯定是不行的,因為ButterKnife是根據傳入的context定位到需要注入的字段mButton,然后通過資源加載器將實例賦值給mButton。ButterKnife能如此干凈利落的完成注入主要完成兩個操作:定位需要注入的view,通過資源加載器注入實例。Dagger2也需要這兩步操作才能像ButterKnife那樣優雅的完成注入,現在已經完成第一個操作(定位需要進入注入的字段),接下來完成第二個操作——添加“資源加載器”。其實我們已經寫好這個“資源加載器”了,就是之前寫的那兩個module類。但是如何把它們關聯起來呢?這時候該Component就出場了。
由于MainActivityComponent只是一個接口,這里直接給出它的源碼
//MainActivityComponent.class

@Singleton
@Component(modules = {DripCoffeeModule.class, PumpModule.class})
public interface MainActivityComponent {
        void inject(MainActivity activity);
}

就是在這里activity與modules建立了聯系,當然這里只是定義的接口,但是通過dagger-compiler庫(配制dagger開發環境時配制好的)可以為該接口生成一個實現DaggerMainActivityComponent。activity與module有了聯系,module提供的實例自然可以注入到activity中需要注入的字段(用@Inject標記的字段)上。注意,每次編輯Component接口(如MainActivityComponent)時,apt會自動調用dagger-compile重新編譯DaggerComponent(如DaggerMainActivityComponent)。好了,現在可以使用Dagger2煮咖啡了,代碼如下:

public class MainActivity extends AppCompatActivity {
        
        @Inject    
        CoffeeMaker mCoffeeMaker;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainActivityComponent.builder()
                    .dripCoffeeModule(new DripCoffeeModule())
                    .pumpModule(new PumpModule())
                    .build().inject(this);
            mCoffeeMaker.brew();
        }
}

輸出

console output

如果代碼沒有錯誤,但是沒有發現DaggerMainActivityComponent類時,重新build一下項目就可以了
rebuild path

如果想看一下DaggerMainActivityComponent或者查看由apt根據dagger-compile規則自動生成的代碼時,到這個目錄下去找
/Dagger2Coffee/app/build/generated/source/apt/debug

這個Demo只是最最基本的Dagger2的用法,還有很多高級用法自己慢慢體會吧。我相信只要入了門,其它的用的多了自然就會了。
咖啡煮完了,回家歇息吧... 這里是Dagger2Coffee源碼。
以下是擴展閱讀

更加強大的Dagger2

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容