#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(); } }
#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