dagger2從入門到放棄-概念
前言
dagger2貌似從兩年前開始在各大android論壇刷屏,一堆Retrofit+RxJava+Dagger2專案如雨後春筍一樣冒了出來。不過當時並沒有趕這個潮流,主要是因為手頭上專案已經較為龐大,而引入dagger2這種入門門檻比較高的庫到專案裡收益並不好估計,當然更明顯的原因就是懶咯。
那現在為啥要用dagger2呢?因為新公司有一套外掛框架,在外掛中引入dagger2的成本相對小了不少,可以實驗性的去嘗試下,但是最終還是決定不在專案中引入dagger2,原因最後一篇文章會說到。
什麼是dagger2
關於dagger2的來龍去脈網上的文章說的足夠多了,也就不多說了,只提下我覺得重要的幾點
- 編譯期的依賴注入框架
- 使用程式碼生成而不用反射
以上兩點決定了dagger2的注入只限於編譯期可以確定的靜態注入,像View,Activity這種執行時產生,且例項是由android框架創建出來的物件只能作為被注入的元件,而無法做為依賴注入到其他地方。當然有舍有得
- dagger2擁有更強的執行時效能
- 較為完善的編譯期程式碼檢查
- 因為在編譯期就生成了全部程式碼,所以除錯也沒什麼問題,不過個人覺得生成的程式碼不夠直觀,除錯起來還是很麻煩
依賴注入框架解決的問題
先說說我理解的依賴
依賴是指某個模組A要實現某個功能需要其他模組B。
最原始也最簡單的的方式是在模組內new一個B的物件出來,這樣會造成B的建構函式修改,需要修改A中的程式碼,兩者耦合度非常高。
依賴注入
依賴注入是不在A中去建立 B的例項,而是讓上層呼叫者注入一個B的物件,這樣可以讓模組A不再因為B的構造方法的修改而改變
注意一點,依賴注入只讓A擺脫了和B的建構函式的耦合,至於A中對B的依賴基於一個實現還是一個介面,依賴注入是管不著的(依賴注入和麵向介面程式設計都是為了模組間解耦但是沒有直接的關係)
如果A依賴於一個介面,而這個介面的實現B又是從外部傳入的,這樣可以讓A完全獨立於B而存在,複用起來就更為簡單
依賴注入帶來的問題
所有的下層模組將建立依賴的任務都往上拋,那麼必然會導致最上層的模組需要建立所有必須的依賴,而到依賴的傳遞過程也會多很多setter或者增加很多構造引數
//網上找的一個比較合適的例子 public class LoginActivity extends AppCompatActivity { LoginActivityPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); OkHttpClient okHttpClient = new OkHttpClient(); RestAdapter.Builder builder = new RestAdapter.Builder(); builder.setClient(new OkClient(okHttpClient)); RestAdapter restAdapter = builder.build(); ApiService apiService = restAdapter.create(ApiService.class); UserManager userManager = UserManager.getInstance(apiService); UserDataStore userDataStore = UserDataStore.getInstance( getSharedPreferences("prefs", MODE_PRIVATE) ); //Activity只需要依賴LoginActivityPresenter //但因為使用了依賴注入,讓下層模組相互解耦,導致activity需要承擔所有依賴的建立任務 //也就多了上面那麼多程式碼 presenter = new LoginActivityPresenter(this, userManager, userDataStore); } }
依賴注入框架的意義
依賴注入框架的目的就在於承擔了最上層建立依賴的職責,並且利用註解在合適的地方注入依賴,簡化依賴的建立和傳遞的模板程式碼
public class LoginActivity extends AppCompatActivity { @Inject LoginActivityPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Satisfy all dependencies requested by @Inject annotation getDependenciesGraph().inject(this); } }
當然簡化掉的程式碼沒那麼誇張,建立依賴的方法只不過是從activity中移到了依賴注入框架中,而依賴注入框架和業務程式碼之間是沒有耦合的,可以按照一定的規則進行復用
dagger2的基本概念

injection.jpg
依賴的提供方
dagger2中有兩種提供依賴的方式
- 使用@Inject註解構造器的類
- 使用在自己可以修改原始碼的類中
- 使用@Module註解包含提供依賴方法的類,使用@Provide方法主角提供依賴的方法
- 用在提供沒有修改原始碼許可權的類的依賴
依賴的需求方
其實也可以分為兩類
- 正常的類,使用了@Inject註解了成員變數的類
- 這裡注入依賴需要自己觸發
- @Inject註解構造器的類
- 這裡@Inject註解的成員變數和構造器引數都會去框架中去找,這個過程是編譯時自動完成的
- 這些類既是依賴的需求方也是依賴的提供方
依賴注入器
使用@Component或者@SubComponent註解的介面或者抽象類
- 描述可以提供哪些依賴
- 描述可以注入到哪些依賴需求方
- 管理依賴的生命週期
也許看完上面一堆你還是一頭霧水,那麼後面就通過程式碼循序漸進來熟悉dagger2吧