Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 依賴注入:Dagger--A fast dependency injector for Android and Java 實例講解

Android 依賴注入:Dagger--A fast dependency injector for Android and Java 實例講解

編輯:關於Android編程

Dagger 是一種android平台的依賴注入框架,是有一家專注於移動支付的公司,Square公司推出的庫,這家公司也推出了

其他在Android開發中常用庫:otto,okhttp,retrofit等等,這些在接下的博文中會一一介紹。

對Dagge的介紹,除了官方文檔的介紹外,接下來的這些分析,本人覺得是比較不錯的,也許在不熟悉Dagger的情況下看這

寫內容,你會覺得無厘頭,不知道講什麼。根據本人經驗,建議先了解Dagger的使用再來看這個會對了解Dagger有比較好的效果。

 

接下來就進入正題,進行實例講解,與官方例子一樣,我這裡也用煮咖啡的例子來說明,只不過官方的例子是用在Java上,這裡

的例子使用Android開發來進行,並且對其也進行了改進。

首先我先說明一下這個過程,既然是煮咖啡,就要由一個加熱器(Heater),加熱之後要有一個倒(Pump)的過程,倒好之後才能供給人

們喝(Drink)。就這麼一個簡單的邏輯,你也許會和我開始一樣,覺得這有什麼難的,很少的代碼就能搞定。是的,我們就要用這麼一

個簡單的事件,來看看用Dagger是怎麼實現的。

首先,我們來設計Heater、Pump、Drink這三個接口,如下:

 

package com.example.app.dagger;

/**
 * Created by zjb on 14-1-22.
 */
interface Heater {
    void on(); //加熱器打開
    void off();//加熱器關閉
    boolean isHot();//加熱是否完畢
}

 

 

package com.example.app.dagger;

/**
 * Created by zjb on 14-1-22.
 */
interface Pump {
    void pump(); //倒咖啡
    boolean isPumped();//是否倒好
}

 

 

package com.example.app.dagger;

/**
 * Created by zjb on 14-1-22.
 */
interface Drink {
    void drink(); //喝咖啡
}
Ok,接口已經設計完畢,是否合理暫且不細究,接下來我們分別實現這三個接口(有用到AndroidAnnotations框架(請看上篇博文)):

 

 

package com.example.app.dagger;
import android.content.Context;
import android.widget.Toast;
import org.androidannotations.annotations.EBean;
import org.androidannotations.annotations.RootContext;
import org.androidannotations.annotations.UiThread;

/**
 * Created by zjb on 14-1-22.
 */
@EBean
class ElectricHeater implements Heater {
    boolean heating = false;
    
    @RootContext
    Context context;
    
    @Override
    public void on() {
        heating = true;
        System.out.println(-----Heating-----);
        reportHeating();
    }

    @UiThread
    void reportHeating(){
        Toast.makeText(context,Electric heater heating.....,Toast.LENGTH_LONG).show();
    }

    @Override
    public void off() {
        heating = false;
    }

    @Override
    public boolean isHot() {
        return heating;
    }
}

ElectricHeater是對Heater接口的實現類,@EBean,@RootContext,@UiThread是AndroidAnnotations框架中的注解。

 

使用@EBean注解會在編譯過程中產生一個ElectricHeater子類ElectricHeater_.class, 接下來會用到。

 

Pump接口實現:

 

package com.example.app.dagger;
import javax.inject.Inject;

/**
 * Created by zjb on 14-1-22.
 */
class Thermosiphon implements Pump {
    private final Heater heater;
    boolean pumped = false;

    @Inject
    Thermosiphon(Heater heater) {
        this.heater = heater;
    }

    @Override
    public void pump() {
        if (heater.isHot()) {
            System.out.println(-----Pumping-----);
            pumped = true;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public boolean isPumped() {
        return pumped;
    }
}

 

 

package com.example.app.dagger;
import javax.inject.Inject;

/**
 * Created by zjb on 14-1-22.
 */
class PeopleDrink implements Drink {
    private Pump pump;
     @Inject
     PeopleDrink(Pump pump) {
        this.pump = pump;
    }
    @Override
    public void drink(){
        if(pump.isPumped()){
            System.out.println(-----Drinking-----);
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
三個接口已經實現完畢,對比三個實現類,有沒有發現什麼共同點. 是的,你會發現,三個類中都有使用@Inject來注解

 

他們的構造函數,這是因為Dagger要用@Inject來注解一個類的實例構造函數,當請求一個新實例的時侯,Dagger就會獲取這個

參數值並調用這個構造函數。也許你不明白,沒關系,繼續往下看,會給出詳細解釋。

Dagger不僅能向上述代碼那樣注解構造函數,也能直接注解fields(Dagger can inject fields directly),看這個類:

 

package com.example.app.dagger;
import javax.inject.Inject;
import dagger.Lazy;
/**
 * Created by zjb on 14-1-22.
 */

class CoffeeMaker {
    @Inject
    Lazy heater;
    @Inject
    Pump pump;
    @Inject
    Drink drink;

    public void brew() {
        heater.get().on();
        pump.pump();
        System.out.println(-----Pumped-----);
        heater.get().off();
        drink.drink();
    }
}
將Heater、Pump及Drink注入到類CoffeeMaker中,就可以直接使用並調用其方法。值得注意的是,在注解的時候Dagger

 

就會通過@Module中的@Provides方法調用構造函數來獲得實例對象(下面馬上介紹)。如果你@Inject fields卻沒有@Inject

構造函數,Dagger就會使用一個存在的無參構造函數,若沒有@Inject構造函數,就會出錯。繼續看@Module

 

package com.example.app.dagger;

import android.content.Context;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;

/**
 * Created by zjb on 14-1-22.
 */
@Module(injects={CoffeeActivity_.class},library = true,complete = false)
/*@Module(injects = {CoffeeActivity_.class},includes = {PumpModule.class,DrinkModule.class},library = true,complete = false)*/
class DripCoffeeModule {
    private final Context context;

    public DripCoffeeModule(Context context) {
        this.context = context.getApplicationContext();
    }

    @Provides
    @Singleton
    Context appliactionContext() {
        return context;
    }

    @Provides
    @Singleton
    Heater provideHeater(){
        return ElectricHeater_.getInstance_(appliactionContext());
    }

    @Provides
    @Singleton
    Drink provideDrink(PeopleDrink drink){
        return drink;
    }

    @Provides
    @Singleton
    Pump providePump(Thermosiphon pump){
        return pump;
    }
}

上面就是使用@Module注解的類,Dagger要求所有的@Provides必須屬於一個Module.他們僅僅是一個使用@Module注解的類。

 

解釋一下前面一句話:如果說@Inject實現了注入,那麼@Provides就是實現依賴關系。@Provides方法方法的返回類型就定義了它

所滿足的依賴。你也許注意到了我注釋掉的@Module,這是什麼意思呢?是這樣的,假如我這裡將providesDrink方法刪除,我可以

另建一個DrinkModule.java文件,由於所有的@Provides必須屬於一個Module,所以必須將DrinkModule類includes進來:

 

package com.example.app.dagger;
import dagger.Module;

/**
 * Created by zjb on 14-1-22.
 */
@Module(library = true,complete = false)
public class DrinkModule {
    @Provides
    @Singleton
    Drink provideDrink(PeopleDrink drink){
        return drink;
    }
}
(@Module後的library和complete是什麼意思這裡先不說)

 

至此,Dagger中的三個重要annotation已經全部涉及到了,那麼它是如何管理這些依賴關系的呢?繼續往下看:

 

package com.example.app.dagger;
import android.app.Application;

import org.androidannotations.annotations.EApplication;

import dagger.ObjectGraph;

/**
 * Created by zjb on 14-1-22.
 */

@EApplication
public class CoffeeApplication extends Application {
    private ObjectGraph objectGraph;

    @Override
    public void onCreate() {
        super.onCreate();
        objectGraph = ObjectGraph.create(new DripCoffeeModule(this));
    }

    public ObjectGraph getObjectGraph() {
        return objectGraph;
    }

}
上邊提到,Dagger是通過什麼管理或者組織依賴關系的呢,就是通過ObjectGraph(對象圖表)。

 

最後的主程序:在節面中就一個按鈕來觸發整個過程

 

package com.example.app.dagger;

import android.app.Activity;
import android.widget.Toast;
import com.example.app.R;
import org.androidannotations.annotations.AfterInject;
import org.androidannotations.annotations.App;
import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.UiThread;
import javax.inject.Inject;
import dagger.ObjectGraph;

/**
 * Created by zjb on 14-1-22.
 */

@EActivity(R.layout.coffee)
public class CoffeeActivity extends Activity {
    @App
    CoffeeApplication coffeeApplication;
    @Inject
    CoffeeMaker maker;

    @AfterInject
    void daggerInject(){
        ObjectGraph objectGraph = coffeeApplication.getObjectGraph();
        objectGraph.inject(this);
    }
    @Click(R.id.coffeeClick)
    @Background
    void coffeeClicked(){
        maker.brew();
        coffeeBrew();
    }
    @UiThread
    void coffeeBrew(){
        Toast.makeText(this,Coffee has been pumped...,Toast.LENGTH_LONG).show();
    }
}

 

程序運行的結果:

 

com.example.app I/System.out﹕ -----Heating-----
com.example.app I/System.out﹕ -----Pumping-----
com.example.app I/System.out﹕ -----Pumped-----
com.example.app I/System.out﹕ -----Drinking-----

 

使用Dagger,我們能夠很好的實現依賴關系,也能更清楚的看到我們的代碼在做些事情,能夠清晰地顯示出各部分的

邏輯關系,通過下面這張圖,我們能夠很清楚的看到它的每一步操作:

 

\


好了,Dagger呢就介紹到這裡,源碼這次就先不上傳了,等到介紹完Otto之後,我會抽空上傳到資源,供大家下載學習。

內容細節說的不全請見諒、指教。如果你對使用dagger有興趣也歡迎一起討論、學習。這是春節前最後一篇文章了,祝大家

搶到一張好票,馬上有錢、有對象!

 

注:文章原創 轉載請注明出處:CSDN 菜鳥的成長史

附:

Jake Warhton的Dagger ppt 下載資源

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved