Dagger2使用(1)

前言

Dagger2是現(xiàn)在非常火一個(gè)注入框架,網(wǎng)上一搜一大堆,看了之后一臉懵逼,還是不怎么懂,研究了一段時(shí)間之后,想自己去整理一下

Dagger2作用

  • 依賴的注入和配置獨(dú)立于組件之外。
  • 因?yàn)閷?duì)象是在一個(gè)獨(dú)立、不耦合的地方初始化,所以當(dāng)注入抽象方法的時(shí)候,我們只需要修改對(duì)象的實(shí)現(xiàn)方法,而不用大改代碼庫(kù)。
  • 依賴可以注入到一個(gè)組件中:我們可以注入這些依賴的模擬實(shí)現(xiàn),這樣使得測(cè)試更加簡(jiǎn)單。

依賴注入

what?依賴注入是什么東東?現(xiàn)在假設(shè)這是你的盲點(diǎn),通過(guò)第一反應(yīng)去解釋一些"依賴注入"。依賴:需要你,need you。注入:給你。連接起來(lái)的意思就是:給你需要的,give you what you need。比如,你要去上班,怎么去呢?開(kāi)車去,那么可以說(shuō)你依賴于車;但是你現(xiàn)在沒(méi)有車,于是你老爸給你買了一輛保時(shí)捷(有這樣的老爸還上班做啥?),給你上班所需要的車,這就是注入。連接起來(lái)就是典型的依賴注入。不懂?那我們通過(guò)代碼的來(lái)擼一擼。

 //定義一輛車
public class Car {
}  
//定義一個(gè)人,這個(gè)人需要一輛車。
public class Person {
Car car;

public Person(Car car) {
  this.car = car;
  }
}

上面這種是在構(gòu)造Person的時(shí)候就注入了Car,因?yàn)镻erson需要一輛Car,而構(gòu)造器正好可以注入Car。因此這是依賴注入的一種方式,我們還可以通過(guò)set方法去注入一輛Car

若是使用Dagger的方式又是怎樣的呢,它能給我們帶來(lái)什么好處?

public class Person {
// dagger2直接使用@Inject
@Inject
Car car;
}

你沒(méi)看錯(cuò),就是直接用@Inject注解就行了,非常的簡(jiǎn)單

實(shí)際操作

上文中通過(guò)"開(kāi)車上班"的例子了解了什么是"依賴注入",那么我們繼續(xù)這例子。我們知道車由發(fā)動(dòng)機(jī),輪子,車座等部件組成。那么,如果我們要造一輛車的話,可能需要這些部件。回歸到代碼中,我們new一個(gè)Car可能需要發(fā)動(dòng)機(jī),輪子,車座等對(duì)象。

我們先來(lái)看看沒(méi)有使用Dagger2的情況

  • 發(fā)動(dòng)機(jī)

    /**
     * 發(fā)動(dòng)機(jī)
     */
    public class Engine {
    
    public Engine(){
    Log.d(Config.TAG,"new Engine()");
    }
    }
    
  • 車座

    /**
     * 車座
     */
    public class Seat {
    public Seat(){
      Log.d(Config.TAG,"new Seat()");
    }
    }
    
  • 輪子

    /**
     * 輪子
     */
     public class Wheel {
     public Wheel(){
      Log.d(Config.TAG,"new Wheel()");
      }
    }
    
  • 上面3個(gè)類用到了Config配置類,其實(shí)就是一個(gè)字符串。

    public class Config {
    public static final String TAG = "TAG";
    }
    

另話:把公共的部分抽取出來(lái),也是代碼規(guī)范的一部分。在今后的工作中,需要不斷review自身代碼,隨著技術(shù)水平的提高,代碼質(zhì)量也需要不斷提高。

上面的代碼中,我們寫了3個(gè)類,都是用來(lái)造車的構(gòu)件。那么對(duì)于造車,對(duì)應(yīng)于我們的代碼就是new Car(),就是這么簡(jiǎn)單。但是Car可能需要Engine,Seat,Wheel 等組件。那么我們來(lái)造個(gè)車試試。

public class Car {
private Engine engine;
private Seat seat;
private Wheel wheel;
public Car() {
    engine = new Engine();
    seat = new Seat();
    wheel = new Wheel();
    Log.d(Config.TAG, "new Car()");
}
}

按照常規(guī)寫法,Car類應(yīng)該是這樣寫。那么我們?cè)趎ew Car()試試。

06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Engine()
06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Seat()
06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Wheel()
06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Car()

就這樣,我們把Car給new出來(lái)了,這樣寫也是沒(méi)有問(wèn)題的。
那么接下來(lái)我們用Dagger2的方式,來(lái)做做試試,先不管他們之間的區(qū)別,just do it。做出來(lái)效果之后再回過(guò)頭來(lái)反思。

Dagger2依賴注入

  1. 在module的build.gradle文件中添加

    annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2' 
    implementation'com.google.dagger:dagger:2.0.2'  
    provided 'org.glassfish:javax.annotation:10.0-b28'
    
  2. 寫一個(gè)Module類,管理上面的三個(gè)依賴。

     @Module
     public class CarModule {
     @Provides
     public Engine provideEngine(){
         return new Engine();
     }
    
     @Provides
     public Seat provideSeat(){
         return new Seat();
     }
    
    @Provides
     public Wheel provideWheel(){
     return new Wheel();
     }
     }
    

3 寫一個(gè)Component類,來(lái)連接Module和你的Car。

@Component(modules = CarModule.class)
public interface CarComponent {
void inject(Car car);
}

4 重寫Car類

public class Car {

@Inject
Engine engine;
@Inject
Seat seat;
@Inject
Wheel wheel;
public Car() {
  DaggerCarComponent
        .builder()
        .carModule(new CarModule())
        .build()
        .inject(this);
Log.d(Config.TAG, "new Car()");

}
}

看看輸出

06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Engine()
06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Seat()
06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Wheel()
06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Car()

是不是達(dá)到了和之前一樣的效果呢?是不是從第3步開(kāi)始,就不知道為什么這樣寫了呢?

分析

我們看看CarModule類是用一個(gè)@Module注解的類,里面的方法是使用@Provides注解。什么意思呢?
@Moudle 表示該類能夠管理并提供依賴;你需要造車,但是車依賴于發(fā)動(dòng)機(jī),輪胎以及車座,那么寫一個(gè)@Module注解的類來(lái)幫你管理這些依賴。
@Provides 表示該方法提供依賴;通過(guò)這個(gè)注解的方法,能給你提供依賴,看代碼應(yīng)該清楚。

我們知道了管理并提供依賴的類,那么我們就可以通過(guò)它來(lái)直接使用依賴。但是Dagger2為了解耦,提供了一個(gè)中介,@Component注解,也就是我們的第4步。

@Component(modules = CarModule.class)
public interface CarComponent {
 void inject(Car car);
}

我們要清楚,@Component就是一個(gè)中間人,里面存著依賴提供者和依賴需求者。在這里

@Component(modules = CarModule.class)

表示的是需要在CarModule類中去尋找依賴,void inject(Car car);這個(gè)方法是抽象的,表示需要將這些依賴應(yīng)用到Car類。說(shuō)白了就是Car類需要CarModule來(lái)提供依賴。

那么我們來(lái)看看@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}.

說(shuō)的是這個(gè)注解只能用于接口或者抽象類。將代碼改成下面,輸出也是一樣的。

@Component(modules = CarModule.class)
public abstract class CarComponent {
public abstract void inject(Car car);
}

在上面的步驟中,我們搞定了依賴提供者,中間人,現(xiàn)在我們要看看依賴需求者。在這我們的需求者是Car,也就是上面寫的Car類。

我們用到了@Inject注解,

@Inject
Engine engine;

上面的代碼表示engine這個(gè)屬性你不用像一般情況去初始化(engine= new Engine()),它能給你自動(dòng)尋找依賴。但是如果是這樣肯定是不行的,還需要

 DaggerCarComponent
    .builder()
    .carModule(new CarModule())
    .build()
    .inject(this);

DaggerCarComponent是apt工具幫我們生成的類,實(shí)現(xiàn)了CarComponent接口。
通過(guò)carModule()將我們的依賴提供者傳入,通過(guò)inject()將我們的Car對(duì)象傳入,這樣就達(dá)到了中間人的目的。

推薦兩篇寫的比較好的文章,Dagger2 最清晰的使用教程
Dagger2神器入門

如果大家對(duì)我的文章感興趣的話, 請(qǐng)為我點(diǎn)贊,謝謝!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 不知不覺(jué)又是一年,這一年,Android技術(shù)與架構(gòu)依舊不斷推陳出新,各種開(kāi)源框架層出不窮,非常感謝大Andr...
    騎小豬看流星閱讀 1,364評(píng)論 1 40
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,094評(píng)論 25 709
  • 每當(dāng)提起自然界中那些體型龐大的動(dòng)物,人們都會(huì)自然想起譬如:恐龍、鯊魚、鱷魚、巨星蜥蜴、蟒蛇等,幾乎不會(huì)把兔子與巨型...
    好睞鼠閱讀 1,250評(píng)論 0 0
  • 冠心病是所有心臟病中國(guó)年發(fā)病率和死亡率最高的疾病,是全身動(dòng)脈粥樣硬化性疾病的一部分。臨床上主要見(jiàn)冠狀血管腔狹窄或阻...
    秋水君閱讀 390評(píng)論 0 1
  • 每天提升能量:1.持續(xù)讀每天的功課,活在功課或富足錄音里;2.冥想;3.每天分享奇跡;4.活在當(dāng)下,接納當(dāng)下的自己...
    海波完美旅程閱讀 247評(píng)論 0 1

友情鏈接更多精彩內(nèi)容