歡迎關注我的微信公衆號,不只是原創技術分享,更多的是生活的思考和總結。
介紹
A fast dependency injector for Android and Java.
一個在 Android 和 Java 平臺上使用的快速的依賴注入框架。
類似 java 開發中的 spring 框架,但使用難度比 spring 大一點點。
依賴注入框架主要用於模塊間解耦,提高代碼的健壯性和可維護性。
幾個必須知道的概念:
什麼是依賴:
如果在 Class A 中,有 Class B 的實例,則稱 Class A 對 Class B 有一個依賴。
什麼是依賴注入:
依賴注入就是非自己主動初始化依賴,而通過外部來傳入依賴的方式,簡單來說就是不使用 new 來創建依賴對象。
三大元素:
必不可少的元素有三種,Module,Component,Container
- Container 擁有者,容器等意思,其中 Activity 就是 Dagger2 中的 Container.
- Component Acitvity 和 依賴對象之間的一個橋樑。
- Module 就是負責提供對象的。
用到的註解如下:
@Inject:
通常在需要依賴的地方使用這個註解。換句話說,你用它告訴 Dagger 這個類或者字段需要依賴注入。這樣,Dagger 就會構造一個這個類的實例並滿足他們的依賴。@Module:
Modules 類裏面的方法專門提供依賴,所以我們定義一個類,用 @Module 註解,這樣 Dagger 在構造類的實例
時候,就知道從哪裏去找到需要的 依賴。modules 的一個重要特徵是它們設計爲分區並組合在一起(比如說,
我們的 app 中可以有多個組成在一起 的modules)@Provide:
在 modules 中,我們定義的方法是用這個註解,以此來告訴 Dagger 我們想要構造對象並提供這些依賴。@Component:
Components 從根本上來說就是一個注入器,也可以說是 @Inject 和 @Module 的橋樑,它的主要作用就是連接這兩個部分。 Components 可以提供所有定義了的類型的實例,比如:我們必須用 @Component 註解一個接口然後列出所有的
官方 Github 地址以及 API 說明文檔::
使用準備:
project 的 build.gradle 添加
dependencies {
... // 其他 classpath
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //添加 apt 命令
}
module 的 build.gradle 添加
// 添加其他插件
apply plugin: 'com.neenbedankt.android-apt'//添加 apt 命令
dependencies {
apt 'com.google.dagger:dagger-compiler:2.0.2' //指定註解處理器
compile 'com.google.dagger:dagger:2.0.2' //dagger 公用 api
provided 'org.glassfish:javax.annotation:10.0-b28' //添加 android 缺失的部分 javax 註解
}
直接從代碼出發吧
代碼完整,可以直接粘貼到自己 AS 驗證。
看一個簡單的例子:
代碼如下:
MainActivity.java
/**
* Created by Veyron on 2017/5/9.
* Function:直接依賴注入 ApiService 對象
*/
public class MainActivity extends AppCompatActivity {
@Inject
ApiService mApiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//rebuild一下,自動生成 DaggerUserComponet 類
DaggerUserComponet.create().inject(this);
mApiService.register();
}
}
ApiService.java
/**
* Created by Veyron on 2017/5/9.
* Function:
*/
public class ApiService {
public void register(){
Log.e("ApiService","register");
}
}
UserModule.java
/**
* Created by Veyron on 2017/5/9.
* Function:提供實例的 Module
*/
@Module
public class UserModule {
@Provides
public ApiService provideApiService(){
Log.e("UserModule","provideUserManger");
return new ApiService();
}
}
UserComponet
/**
* Created by Veyron on 2017/5/9.
* Function:Activity 和 Module 之間的橋樑
* @Component(modules = {UserModule.class}) 表示和 Module 對接
*
* void inject(MainActivity activity);表示在 MainActivity 中注入
*/
@Component(modules = {UserModule.class})
public interface UserComponet {
void inject(MainActivity activity);
}
輸出:
E/UserModule: provideApiService
E/ApiService: register
更復雜一點的例子:
MainActivity.java
/**
* Created by Veyron on 2017/5/9.
* Function:直接依賴注入 UserManger 對象
*/
public class MainActivity extends AppCompatActivity {
/* @Inject
ApiService mApiService;*/
@Inject
UserManger mUserManger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder()
.userModule(new UserModule()).build().inject(this);
//DaggerUserComponet.create().inject(this); 等價上面
mUserManger.register();
}
}
ApiService.java
/**
* Created by Veyron on 2017/5/9.
* Function:直接依賴注入 UserManger 對象
*/
public class ApiService {
//當module裏面沒有提供本類的對象,默認調用下面這個 @Inject 註釋的構造函數(只能聲明一個)
@Inject
public ApiService(){
Log.e("ApiService","ApiService的構造函數");
}
/* @Inject
public ApiService(String url){
Log.e("ApiService","url---");
}*/
public void register(){
Log.e("ApiService","register");
}
}
UserModule.java
/**
* Created by Veyron on 2017/5/9.
* Function:
*/
@Module
public class UserModule {
@Provides
public ApiService provideApiService(){
Log.e("UserModule","provideApiService-");
return new ApiService();
}
@Provides
public String url(){
return "url";
}
// 將會調用這個 public ApiService(String url) 方法
//單獨調用本方法的話,apiService 的對象是上面提供的,另一種使用 apiservice 的構造方法
@Provides
public UserManger provideUserManger(ApiService apiService){
Log.e("UserModule","provideUserManger");
return new UserManger(apiService);
}
}
UserComponet.java
/**
* Created by Veyron on 2017/5/9.
* Function:Activity 和 Module 之間的橋樑
* @Component(modules = {UserModule.class}) 表示和 Module 對接
*
* void inject(MainActivity activity);表示在 MainActivity 中注入
*/
@Component(modules = {UserModule.class})
public interface UserComponet {
void inject(MainActivity activity);
}
輸出如下:
E/UserModule: provideApiService
E/ApiService: ApiService 的構造函數
E/UserModule: provideUserManger
E/UserManger: register
E/ApiService: register
更復雜點
第二個例子其中,將 UserModule.java,UserModule.java 改動如下:
UserModule.java
/**
* Created by Veyron on 2017/5/9.
* Function:
*/
@Module
public class UserModule {
/*@Provides
public ApiService provideApiService(){
Log.e("UserModule","provideApiService");
return new ApiService();
}*/
@Provides
public String url(){
return "傳給 ApiService 構造函數的參數";
}
// 將會調用這個 public ApiService(String url) 方法
//單獨調用本方法的話,apiService 的對象是上面提供的,另一種使用 apiservice 的構造方法
@Provides
public UserManger provideUserManger(ApiService apiService){
Log.e("UserModule","provideUserManger");
return new UserManger(apiService);
}
}
ApiService.java
/**
* Created by Veyron on 2017/5/9.
* Function:@Inject 聲明的構造函數只能有一個
*/
public class ApiService {
//當module裏面沒有提供本類的對象,默認調用下面這個 @Inject 註釋的構造函數(只能聲明一個)
/*@Inject
public ApiService(){
Log.e("ApiService","ApiService的構造函數");
}*/
@Inject
public ApiService(String url){
Log.e("ApiService","url="+url);
}
public void register(){
Log.e("ApiService","register");
}
}
輸出是:
E/ApiService: url=傳給ApiService構造函數的參數
E/UserModule: provideUserManger
E/UserManger: register
E/ApiService: register
看了輸出,再參考下代碼,其實就知道是怎麼回事了。
可以得到一點結論就是:在 UserModule 中需要 ApiService 對象,但是 UserModule 中並沒提供,那麼就去查看 ApiService 中有沒有 @Inject 聲明的構造函數,如果有且是無參構造函數,那麼 UserModule 中就相當拿到了 ApiService 對象。如果是有參的構造函數,則 UserModule 中必須有提供該參數的實例,如本例子中的 public String url() 函數,返回的 String 就是給構造函數當參數的,那麼 UserModule 中就等於有了 ApiService 對象。
聲明
建議把上面的例子都運行一遍,就會有體會 Dagger2 的使用是怎樣的。
篇幅有限,Dagger2 使用方式也有很多, 下一篇接着介紹 其他例子。