- 該系列部落格的最終目標: 搭建 MVP + Dagger2 框架
- 該系列部落格包含以下幾篇內容:
- Dagger 2 系列(一) -- 前奏篇:依賴注入的基本介紹
- Dagger 2 系列(二) -- 基礎篇:@Inject、@Component
- Dagger 2 系列(三) -- 基礎篇:@Module 和@Provides
- Dagger 2 系列(四) -- 基礎篇:@Named 和 @Qualifier
- Dagger 2 系列(五) -- 進階篇:@Scope 和 @Singleton
在這篇文章中你會看到什麼:
@Module
是什麼@Provides
是什麼@Module
、@Provides
和@Component
如何協同作戰。
1. 什麼是 Module
既然在Dagger 2 系列(二) -- 基礎篇:基本功能的實現一文中通過 @Inject
和 @Component
我們已經實現了 DI,那麼為什麼 Dagger2
還要實現其他的DI 方式。
其實在上文中我們實現的 DI 方式中我們不難發現,通過@Inject
的註解實體類的建構函式是必不可少,它標識著 Dagger2 可以例項化該類。那麼當你需要例項化一個第三方的物件時,是不是懵逼了,因為你不可能註解第三方類的建構函式 -- 比如說 Gson
類的建構函式。那麼現在就需要 @Module
來充分發揮作用了。
其實Module 其實是一個簡單工廠模式,Module 裡面的方法都是建立相應類例項的方法。
具體什麼是 簡單工廠模式,請看程式碼段簡單學習設計模式 -- 簡單工廠模式
栗子:通過 @Module
的方式獲得第三方類庫的物件 -- Gson
(當然也可以獲得自定義類物件)
@Module
public class AModule {
@Provides
public Gson provideGson(){
return new Gson();
}
}
複製程式碼
你再該類中看到了兩個註解:
- 通過
@Module
註解類 - 通過
@Provides
註解方法
1.2 新增多個 Module
一個 Component
可以含有多個 Module
,這樣在尋找依賴例項時就會自動從多個 Module
中尋找。
新增 多個 Module
的方法有兩種:
1.2.1 Component 註解 -- @Component(modules={××××,×××})
示例程式碼如下:
@Component(modules={ModuleA.class,ModuleB.class,ModuleC.class})
public interface AppComponent{
...
}
複製程式碼
1.2.2 Module 註解 -- @Module(includes={××××,×××})
示例程式碼如下:
@Module(includes={ModuleA.class,ModuleB.class,ModuleC.class})
public class FruitModule{
...
}
@Component(modules={FruitModule.class}) //新增多個Module
public interface AppComponent{
...
}
複製程式碼
這種使用 Module
的 includes
新增多Module
的方法一般用於構建更高層的Module
時候使用,如在本例中
2. 什麼是 Provides
@Provides
用以標註 Module
類中的方法,它的作用是 標註該 Module
可以向外界提供的類的例項物件的方法 ,就像 AModule
中可以提供 Gson
例項物件的 provideGson()
方法。
3. Component -- 管理 Module
此時 DI 不是通過 @Inject
註解類構造器的方式,那麼這個註解器的使用方法肯定也有所變化。此時 Component 的職責是管理 Module,Component 中的屬性允許 Module 可以加入到 Component,同時一個 Component 可以加入多個 Module。
依賴注入的具體工作流程:
若例項化過程中引數同樣是需要依賴注入的,那麼需要按照上圖中的流程一樣尋找相應的方法。如果遍歷了元件中管理的 Module 類中的 @Provides 註解的方法,那麼就會尋找該例項類的構造器中是否有被 @Inject 註解的,如果引數同樣有需要依賴注入的,那麼就重複以上過程。如果最終還是沒有找到相應的初始化例項的方法,那麼程式會報出相應的錯誤。
4. 程式碼示例
@Component(modules = UserTwoModule.class)
public interface UserTwoComponent {
void injectToSecondActivity(SecondActivity mSecondActivity);
}
@Module
public class UserTwoModule {
@Provides
UserTwo provideUserTwo(){
return new UserTwo("男",1243);
}
}
public class SecondActivity extends AppCompatActivity {
@Inject
UserTwo mUserTwo;
private static final String TAG = "SecondActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
DaggerUserTwoComponent.builder().userTwoModule(new UserTwoModule()).build().injectToSecondActivity(this);
}
}
複製程式碼
總結
到此為止,我們已經實現了基本的基於Dagger2
的@Module
和@Provides
的依賴注入。下面我們把過程再梳理一遍:
- 用@Inject註解標註目標類中其他類
- 在
Module
中建立返回值為相應實體類的方法,並用@Provides
標註 - 若其他類還依賴於其他的類,則重複進行上面2個步驟
- 呼叫
Component
(注入器)的injectXXX
(Object)方法開始注入(injectXXX
方法名字是官方推薦的名字,以inject開始)
Component 就像媒介,連線 Module
和 目標類
,把目標類依賴的例項注入到目標類中,來初始化目標類中的依賴。