Dagger2圖文徹底教程

#Dagger2圖文徹底教程java


本文屬代碼GG原創,非經本人贊成,禁止轉載。android

須要交流,聯繫微信:code_gg_boy 更多精彩,時時關注微信公衆號code_gg_homegit

一個顯示圖

沒有更多開場白,直接說下我對它的理解。github

Dagger2 是一個Android依賴注入框架。而android開發當前很是流行的非MVP模式莫屬了,Dagger2的目標即是將MVP中的V P 進一步解耦,達到模塊化最大的解耦,使得代碼更容易維護。微信

舉個栗子:有個A對象 B對象 和C對象,若是C對象建立須要A和B,那麼咱們是否是須要構造裏面傳入參數A和參數B,而後在使用的地方以下寫個代碼:框架

C c=new C(new A(),new B());

若是咱們使用了Dagger2時候,咱們就不須要管這些了,只須要關聯住能提供建立A 和 B的地方 ,而後在須要C的地方寫下:ide

@Inject
C c;

而後在這個類的初始化地方進行注入便可。 咱們初步來看,會發現Dagger2優點不大,沒什麼吸引人的,那麼請你靜下心來,看完再得出結論。模塊化


閒話休敘,咱們來直接上代碼:(常規寫法)學習

#1 編寫一個類:測試

public class Test3 {
    public Test3() {
    }
}

#2 使用的地方

public class MainActivity extends AppCompatActivity {
    Test3 test3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //.....
        test3 = new Test3();
    }
}

  • 若是咱們改成使用Dagger2的方式的話,則能夠寫成以下方式:

#1 建立一個類

使用了註解方式,使得Dagger2能找到它。

public class Test3 {
    //這裏能夠看到加入了註解方式
    @Inject
    public Test3() {
    }
}

#2 新增一個對象:

@Singleton
//用這個標註標識是一個鏈接器
@Component()
public interface MainActivityComponent {
    //這個鏈接器要注入的對象。這個inject標註的意思是,我後面的參數對象裏面有標註爲@Inject的屬性,這個標註的屬性是須要這個鏈接器注入進來的。
    void inject(MainActivity activity);
}

#3 調用的地方改成:

public class MainActivity extends AppCompatActivity {
    //加入註解,標註這個test3是須要注入的
    @Inject
    Test3 test3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //使用組件進行構造,注入
        DaggerMainActivityComponent.builder().build().inject(this);
    }

這是最簡單的一種使用了。首先咱們看到,第一印象是我去,這個更復雜了啊。我只能說確實,由於這個是它對的最基礎的使用,看起來很笨拙,可是當它在大型項目裏面,在依賴更多的狀況下,則會發生質的飛躍,會發現它很是好用,而且將你須要傳遞的參數都隱藏掉,來實現解耦。


我先說下Dagger2的註釋思路:關鍵的點是@Component,這個是個鏈接器,用來鏈接提供方和使用方的,因此它是橋樑。它使用在組件裏面標記使用的Module(標記用到了哪一個Module,主要是看使用方須要哪些對象進行構造,而後將它的提供方@module寫在這裏) 而後咱們寫入一個void inject(MainActivity activity); 這裏後面的參數,就是咱們的使用方了。如此一來,咱們在使用的地方,使用相似這種方式(DaggerMainActivityComponent.builder().build().inject(this);)的動做,將使用方類裏面的標記 爲@Inject的類初始化掉,完成自動初始化的動做。

結構以下:

一個顯示圖

爲了更好的來學習它,咱們來依次看看各類使用狀況。

#1 常規使用方法

一個顯示圖 一個顯示圖 一個顯示圖

直接感覺下,如何?

#2 帶一個參數的效果


一個顯示圖


一個顯示圖


一個顯示圖


咱們來看一個代碼段,當咱們建立兩個實例的時候,發現地址是獨立的。

一個顯示圖

若是咱們想要同樣的地址呢?加上一句話,具體以下:

一個顯示圖

效果即是兩個共用實例啦。

一個顯示圖

#3 換種常用的方式

將提供的構造,放入@module裏面,具體效果以下:

一個顯示圖

去掉標記的@singleton後

一個顯示圖

效果變成獨立的啦

一個顯示圖

#4 依賴一個組件的時候

有時咱們須要依賴一個組件,這個最多見的用法是,咱們App實例裏面提供了好比獲取sharepreference的實例,和好比如今代碼裏面的LocationManager的實例,咱們Activity裏面須要這些實例,咱們該如何來作呢?看效果: 1:一個AndroidModule 模塊標記

一個顯示圖

這個模塊屬於AndroidcationComponent 組件裏面

一個顯示圖

這裏有個關鍵點,就是子組件須要這個裏面的某個實例的時候,這裏須要使用一個接口,將須要的實例作一個返回動做。這裏是LocationManager這一行。

咱們的子組件的代碼以下:

一個顯示圖

對應的Cmodule代碼以下:

一個顯示圖

再來看下Test3的代碼當前狀況:

一個顯示圖

使用的地方:

一個顯示圖


細心的你會發現這裏多了一個註釋了,@PerActivity,它是個什麼鬼呢?

一個顯示圖

這裏咱們看到它是使用了@Scope的一個註釋,這個註釋的意思就是做用域,在做用域內保持單例,能夠直接理解爲單例便可。 爲何要新增一個呢,主要是由於各個組件須要獨立出來,所以若是是依賴關係,則須要各自在不一樣的註釋做用域裏面。 咱們來看下在Cmodule裏面,加上@perActivity註釋後的效果:

一個顯示圖

一個顯示圖

若是去掉呢?

一個顯示圖

咱們忽然發現,它和單例的註釋起的做用同樣啊。so。。。是否是發現什麼啦。

一個顯示圖

所以咱們得出一個結論,這裏@Singleton 就是一個普通的做用域通道,使用了做用域@Scope註釋的代碼,會變成單例模式。爲了驗證咱們的思路,做以下測試:

一個顯示圖

一個顯示圖

咱們將以前的@Singleton用新建的這個替換掉,驗證兩次的生成代碼,發現如出一轍,如出一轍,如出一轍,so。。。 就是這個樣子啦。

#5 自定義一個標記 爲何要自定義標記呢?這個標記不是使用@Scope註釋的哦,是使用@Qualifier 標記的,它的目標是,爲了區分若是同時返回類型同樣,好比構造男孩,女孩的基本屬性,性別和名字時候,獲取男孩和女孩都是一個對象,咱們該如何區分呢,這個就是關鍵啦。說這麼多,真心很煩,直接栗子來啦。

這裏稍安勿躁,先來看相同效果的另外一個註釋,@Name,這個是Dagger2自帶的一個讓區分,效果以下:

一個顯示圖

一個顯示圖

一個顯示圖

一個顯示圖

這裏@Name能夠簡單的一個使用方式,就是它不是區分對象,而是限制使用時候必須加入這個註釋,不然報錯,目的就是讓使用者注意是否使用正確了。

一個顯示圖

一個顯示圖

咱們使用本身的註釋再來一遍:

一個顯示圖

一個顯示圖

一個顯示圖

一個顯示圖

一個顯示圖

對比兩種方式,咱們發現使用@Name的時候,後面的註釋名字會敲錯,而咱們第二種方式呢,則不會耶,so。。。

咱們看下自定義的標記,做爲限制出錯,讓強制標註的例子。

一個顯示圖

一個顯示圖

一個顯示圖

一個顯示圖

#6 子組件(公共組件) 這個出現的目的是爲了若是有一個組件,是每次建立實例提供給別人,而剛好其餘組件(有多個)裏面有須要它,若是隻有一個,咱們就用依賴搞定啦。那麼它就能夠定義成子組件,誰須要在誰的組件裏面加一下,具體看例子:

一個顯示圖

一個顯示圖

一個顯示圖

如上,寫完啦。。

實戰地方,能夠參照 https://github.com/gzsll/TLint 來閱讀啦,收工。 須要交流,聯繫微信:code_gg_boy 更多精彩,時時關注微信公衆號code_gg_home

一個顯示圖

相關文章
相關標籤/搜索