Dagger2分析學習
Dagger學習筆記
1.概要
Dagger是為Android和Java平臺提供的一個完全靜態的,在編譯時進行依賴注入的框架,原來是由Square公司維護的然后現在把這堆東西扔給
Google維護了
控制反轉(Inversion of Control,縮寫Ioc),是面向對象編程中的一種設計原則,可以用來減少計算機代碼之間的耦合度,其中最常見的方式是依賴注入
(Dependency Injection),還有一種叫做“依賴查找”(Dependency Lookup),通過控制反轉對象在創建的時候,有控制系統內所有對象的外界實體,將其
所有依賴的對象的引用傳遞給它,也可以說,依賴注入到對象中。
應用Dagger2的依賴庫:
項目根目錄的配置文件中配置:
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' (annotation processing tools)//注解處理工具
主要是用在java編譯的過程中解析java文件中的注解類型,從而產生代碼來替換掉源碼中的注解的功能。
}
}
//應用apt插件
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
provided 'org.glassfish:javax.annotation:10.0-b28'
}
依賴注入的三種方式:
public class CoffeeMachinWithInjection implements InjectMaker{
private CoffeeMaker maker;
/*依賴注入的3種常見形式
*No.1 構造函數注入
*/
public CoffeeMachinWithInjection(CoffeeMaker maker){
this.maker = maker;
}
//No.2 Setter注入
public void setMaker(CoffeeMaker maker){
this.maker = maker;
}
// //No.3 接口注入
@Override
public void injectMaker(CoffeeMaker maker) {
this.maker = maker;
}
public String makeCoffee(){
return maker.makeCoffee();
}
}
上述的表示中我們在平時的代碼開發中常使用到的代碼開發方式,手動提供注入,解決了使用在類內部使用時new一個新的對象。下面我們看是來對
Dagger2進一步使用講解。動態的解決掉依賴注入。
在Dagger中我們有六種注解:
1.Inject:兩個作用
1.在宿主中表明需要注入的類
2.在需要實例化的類中的構造方法上使用,表明需要注解(沒有構造參數的類上號使用,在有構造參數的類中需要使用在module中使用@provides提供)
2.Component:主要是在產生依賴的類之間生成通信的橋梁
3.module:專門用來提供依賴
4.provides:用來在module中專門提供產生依賴的類,主要用來標記提供依賴的方法
這里再說明一個問題,我們有兩種方式可以提供依賴,一個是注解了@Inject的構造方法,一個是在Module里提供的依賴,那么Dagger2是怎么選擇依賴提供的呢,規則是這樣的:
- 步驟1:查找Module中是否存在創建該類的方法。
- 步驟2:若存在創建類方法,查看該方法是否存在參數
- 步驟2.1:若存在參數,則按從步驟1開始依次初始化每個參數
- 步驟2.2:若不存在參數,則直接初始化該類實例,一次依賴注入到此結束
-
步驟3:若不存在創建類方法,則查找Inject注解的構造函數,看構造函數是否存在參數
2.dagger2調用過程
dagger2的調用流程如上圖所示:
Dagger2有三個構建組成:從上到下依次為:
1.依賴需求方(宿主),需要使用對象實例的類。
2.依賴提供方,統一提供實例類型或數據掉用的類。
3.依賴注入構件(Component),負責管理module產生的數據注入到宿主中,在編程中表現為一個接口,編譯時apt自動回生成一個以Dagger開頭的類。
上圖中從上到下依次對應上述的三個部分。下面先分析上面代碼的表現形式:
在Activity中得到LoginActivityComponont:
DaggerLoginActivityComponont.builder()
.appComponent(AppGlobalState.getInstances().getComponent())
.loginModule(new LoginModule(this, this))
.volidateModule(new VolidateModule())
.build()
.inject(this);
LoginActivity中使用inject(this)方法來獲取建立與依賴注解類相關聯。先查看一下LoginActivityComponont類的實現:
/**
* Created by cangck on 17/5/19.
*/
@MainActivityScope
@Component(modules = {LoginModule.class, VolidateModule.class}, dependencies = AppComponent.class)
public interface LoginActivityComponont {
LoginActivity inject(LoginActivity activity);
}
在這個類中我們使用到了的注解說明:@MainActivityScope
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface MainActivityScope {
}
@scope又是Dagger2的一個域修飾符,對對象提供的范圍的一個限制
@Target(ANNOTATION_TYPE)
@Retention(RUNTIME)
@Documented
public @interface Scope {}
@Singleton實例表示時,單例返回@Module
public class AppModule {
private Application mApplication;
public AppModule(Application application) {
this.mApplication = application;
}
@Singleton
@Provides
public Application provideApplication() {
return mApplication;
}
}
LoginModule的實現
@Module
public class LoginModule {
private LoginActivity mActivity;
private ILoginView mLoginView;
public LoginModule(LoginActivity activity, ILoginView loginView) {
this.mActivity = activity;
this.mLoginView = loginView;
}
@Provides
public LoginActivity providesActivity() {
return mActivity;
}
@Provides
public ILoginView proivdeLoginView() {
return mLoginView;
}
@MainActivityScope
@Provides
public LoginUserBean getUserData() {
LoginUserBean userBean = new LoginUserBean();
userBean.setName("cck");
userBean.setAge(20);
return userBean;
}
@Provides
public LoginPresenter provideLoginPresenter(LoginActivity activity, ILoginView loginView) {
LoginPresenter presenter = new LoginPresenter(activity, loginView);
return presenter;
}
}
@MainActivityScope這個注解是對@Scope的擴展,表示只用在Component組件上使用@MainActivityScope注解是才能調用getUserData方法
- component 的 inject 函數不要聲明基類參數;
- Scope 注解必須用在 module 的 provide 方法上,否則并不能達到局部單例的效果;
- 如果 module 的 provide 方法使用了 scope 注解,那么 component 就必須使用同一個注解,否則編譯會失敗;
- 如果 module 的 provide 方法沒有使用 scope 注解,那么 component 和 module 是否加注解都無關緊要,可以通過編譯,但是沒有局部單例效果;
- 對于直接使用 @Inject 構造函數的依賴,如果把 scope 注解放到它的類上,而不是構造函數上,就能達到局部單例的效果了;
@Provides
public ILoginView proivdeLoginView() {
return mLoginView;
}
@Provides
public LoginUserBean getUserData() {
LoginUserBean userBean = new LoginUserBean();
userBean.setName("cck");
userBean.setAge(20);
return userBean;
}
上面代碼中使用@provides注解方法,當調用對象時,注解工具會在在方法中查找使用@provides注解的方法,并且根據返回值來確認是通過那個方法來提供數據。
注:方法的調用使用過返回值來確認的
下列類為VolidateModule的實現
/**
* Created by cangck on 17/5/19.
*/
@Module
public class VolidateModule {
}
先列舉上面的兩個類來作為使用說明就Ok了我們先觀察一下LoginActivityComponont類上我們使用了注解
@MainActivityScope
@Component(modules = {LoginModule.class, VolidateModule.class}, dependencies = AppComponent.class)
在上面已經介紹過了LoginActivityComponont類使用了注解@Component之后就好變成了Dagger2中的組件控制器。在觀察上圖,
@Component的注解參數:1.modules,2.dependencies
1.modules表示當前的Component管理LoginModule,VolidateModule,當需要使用類實例時當前的Component只能從上述的兩個類的范圍中來查找,不會到其他的類中去找。
2.dependencies:相當于類的繼承關系,當前的Component不僅可以從自己管理的類中類獲取對象,亦可以使用AppComponent提供的方法來使用。
Dagger2之間的三個組件關聯的方式已經介紹完成:
1.LoginActivity中使用inject(this)的方法和Dagger2中的組件Component建立關系。
2.Component與module建立聯系是通過@Component(moudel={aModule.class,BModule.class},dependecies=DComponent.class)
4.Component的聲明周期:
1.創建Component實例
DaggerLoginActivityComponont.builder()
.appComponent(AppGlobalState.getInstances().getComponent())
.loginModule(new LoginModule(this, this))
.volidateModule(new VolidateModule())
.build()
.inject(this);
- onCreate()方法調用完成后,Component實例就會因為沒有被引用而被垃圾回收器回收.其中傳入給Component實例的Module實例也會一同被回收,這也就能說明不同的Component實例之間是沒有聯系的(Component依賴除外).這里需要注意的是,使用Lazy和Provider時,與該依賴對象有關的Module實例會被Lazy和Provider引用,所以該Module實例不會被垃圾回收器回收
Dagger2 入門,以初學者角度. Dagger2 入門,以初學者角度.
Dagger2 Scope 注解能保證依賴在 component 生命周期內的單例性嗎?
Android:dagger2讓你愛不釋手-重點概念講解、融合篇
智能推薦
dagger2的生成源碼簡單分析
dagger2官方GitHub: 點擊打開鏈接 直接上圖,自己對dagger2構架的見解: 這里使用的是官方的實例分析的. 并稍微修改了CoffeeApp 然后生成 : CoffeeApp會被編譯器生成如下代碼: 這DaggerCoffeeApp的作用:對module,提供者和類注入器(現在還沒有)進行初始化,也是一個交互的場所. 然后根據module 提供的實例的方法生成&...
Dagger2 Android依賴注入學習
前言 最近在用 MVP + RxJava + Retrofit 寫項目,覺得相對于其他的開發框架,這的確是給我們帶來了很多方便,但是在網上搜尋相關資料的時候,總是能看到 MVP + RxJava + Retrofit + Dagger 這樣的搭配組合,那 Dagger 又是一個怎樣的框架呢,我也去具體搜了搜,但看到一些文章帶著“Dagger2從入門到放棄&rdq...
安卓開發學習之Dagger2的使用
今天閑來無事,就總結一下前些日子對Dagger2的學習使用 介紹 Dagger2是一個利用注解來構造類的實例的東西,網上稱此為依賴注入。 Dagger2主要有這么幾個注解@Inject、@Module、@Provides、@Component、@Qualifier和@Scope。在這篇文章中,我會為大家一一演示它們的簡單用法,供大家入門。 場景構造 我們先構造一個場景:咖啡店造咖啡 ...
學習Dagger2筆記:【4】@Component
目錄 0. 前言 1. 依賴與注入 2. @Inject 3. @Module & @Provides 4. @Component 5. @Qualifier 6. Provider & Lazy 7. @Scope 8. 注入到Set和Map容器 9. Bind系列注解 10. dagger中依賴關系與繼承關系 11. dagger.android 目標 上一篇說到我們想要dag...
Dagger2使用詳解
Dagger2 是一個Android依賴注入框架,由谷歌開發,最早的版本Dagger1 由Square公司開發。依賴注入框架主要用于模塊間解耦,提高代碼的健壯性和可維護性。 Dragger2 通過注解來生成代碼,定義不同的角色,主要的注解有:@Inject、@Module、@Component、@Provides、@Scope、@SubComponent等。 @Inject:通常在需要依賴的地方使...
猜你喜歡
Dagger2入門詳解
Dagger2 確實比較難學,我想每個開發者學習的時候總是經歷了一番痛苦的掙扎過程,于是就有了所謂的從入門到放棄之類的玩笑,當然不排除基礎好的同學能夠一眼看穿。本文的目的嘗試用比較容易理解的角度去解釋 Dagger2 這樣東西。 Dagger2 是有門檻的,這樣不同水平能力的開發者去學習這一塊的時候,感受到的壓力是不一樣的。 我個人總結了大家在學習 Dagger2 時,為什么感覺難于理解的一些原因...
快速入門Dagger2
1、Dagger2的介紹和簡單使用: A fast dependency injector for Android and Java. 一個快速的依賴注入庫為java和android, 什么是依賴注入?有興趣的同學可以看一下我之前轉載的一篇依賴注入的文章。 https://github.com/google/dagger 這是Dagger2的github地址,里面介紹了在項目中如何使用和依賴。 1...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...