Dagger是一個完全靜態的,在編譯時進行依賴注入的框架,原來是由Square公司維護的然後現在把這堆東西扔給Google維護了。Dagger解決了基於反射帶來的開發和性能上的問題(因爲Dagger並沒有用反射來做依賴注入)說了那麼多,其實就是告訴我們這傢伙可以用來做依賴注入哦。
依賴注入:我們在做項目時,經常需要在一個對象裏去創建另一個對象的實例,這種行爲是產生耦合的常見形式,對於一個大型項目來說,過多的相互依賴會導致代碼難以維護,很容易就會碰到修改一個小需求需要大面積的修改各種代碼,特別是代碼原來不是自己維護的,擼着代碼的你就開始問候別人家的親友了。
在需要依賴的類中不要通過new來創建依賴而是通過方法提供的參數注入進來,這樣我們的需要依賴的類和提供依賴的類的實現方法分隔開了,一切又變得如此美好咯。
dagger2是一個依賴注入框架,在編譯期間自動生成代碼,負責依賴對象的創建。
用dagger2提供依賴有什麼好處:爲了進一步解耦和方便測試,我們會使用依賴注入的方式構建對象 (不使用 new 來創建依賴對象)。在mvp中,presenter層會持有view和model層的依賴,依賴注入主要用於解耦,通過依賴注入創建對象,不再使用new來創建對象。
依賴注入的目的是:給你提供一個對象依賴。
Dagger2的常用註解:
@Inject:此註解用於告訴Dagger2,我們需要這個類的實例對象。主要用於標記哪個類是需要注入的。
@Module:此註解裏面全是方法,用於對外提供對象,自己定義方法,方法上使用@Provides。自定義一個類,以Module結尾,用@Module註解。
@Provides:此註解用於標記方法,表示可以通過這個方法獲取一個對象,一般用於自定義類中。
@Component:此註解主要用於關聯自定義module類和MainActivity;關聯module使用:@Component(modules={UserModule.class});關聯Activity,以方法參數的形式傳入MainActivity到連接器中
@Named與@Qualifier:用於區別不同對象的實例。必須要成對出現,否則會報錯。
@PerActivity:限定對象的生命週期和Activity一樣。一般應用於自定義的Component上。
@Singleton:標記爲單例模式,如果在自定義Module中使用了此註解,在自定義的Component上也要使用該註解。
使用方式:
1)自定義Module,裏面的方法用於提供依賴,
2)自定義Component接口,裏面全是Activity的注入方法,
3)按Ctrl+F9進行編譯。
自定義Module類:
自定義module中的方法 要以provide開頭
通過構造方法傳遞Context
如果定義的module,需要傳參數,就需要在Activity使用build進行諸如
添加依賴:
//添加依賴
compile 'com.google.dagger:dagger:2.9'
annotationProcessor 'com.google.dagger:dagger-compiler:2.9'
MainActivity代碼:此依賴注入的目的是獲取ApiService類的實例,然後調用其中的register方法;編譯後會自動生成DaggerUserComponent類
package com.example.administrator.testdragger2.old;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.administrator.testdragger2.R;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
ApiService apiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Dagger會自動創建這個類,以Dagger開頭+UserComponent
DaggerUserComponent.create().inject(this);
apiService.register();
}
}
UserComponent代碼:自定義接口
package com.example.administrator.testdragger2.old;
import dagger.*;
/**
* Created on 2017/5/8.
* Author:crs
* Description: UserComponent連接器,橋樑
*/
@Component(modules = {UserModule.class})
public interface UserComponent {
//當前只能寫MainActivity,不能寫Activity,要不然會出現空指針。
void inject(MainActivity activity);
}
UserModule代碼:自定義module類,主要用於提供依賴
package com.example.administrator.testdragger2.old;
import dagger.Module;
import dagger.Provides;
/**
* Created on 2017/5/8.
* Author:crs
* Description:用於提供依賴
*/
@Module
public class UserModule {
@Provides
ApiService provideApiService(){
return new ApiService();
}
}
ApiService類:
package com.example.administrator.testdragger2.old;
import android.util.Log;
/**
* Created on 2017/5/8.
* Author:crs
* Description:ApiService
*/
public class ApiService {
private static final String TAG = "ApiService";
public void register() {
//請求網絡數據
Log.i(TAG,"測試數據");
}
}
———————————————————————————————————————>
如果自定義類module中的方法,需要一個對象參數,怎麼處理?需要一個方法去提供這個對象。
1)在類的構造方法上添加@Inject註解
2)自己寫一個方法去提供參數對象
package com.example.administrator.testdaggger2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserStore userStore;
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//主要兩個問題:
//1)自定義Module需要傳遞上下文怎麼辦
//2)自定義Module中的方法中需要參數對象怎麼處理?(構造函數、自己提供方法)
//Dagger會自動創建這個類,以Dagger開頭+UserComponent,編譯時注入,按Ctrl+F9編輯即可
//DaggerUserComponnent.create().inject(this);
//userManager.register();
//Dagger的關係非常簡單,MainActivity中需要對象,那麼就在Module中提供對象;而他們之間的橋樑就是componnent
//自定義類Module的構造方法中需要傳入一個上下文對象,那麼在MainActivity中就需要傳遞進去。
//使用下面的這種方式進行參數傳遞:this就是上下文
DaggerUserComponnent.builder().userModule(new UserModule(this)).build().inject(this);
userManager.register();
}
}
package com.example.administrator.testdaggger2;
import android.content.Context;
import dagger.Module;
import dagger.Provides;
/**
* Created on 2017/5/9.
* Author:crs
* Description:XXX
*/
@Module
public class UserModule {
//在Module中傳遞上下文對象
private Context mContext;
public UserModule(Context context) {
this.mContext = context;
}
@Provides
UserStore provideUserStore(){
return new UserStore();
}
//如果自定義Module中的方法需要對象參數,怎麼處理?
//1)通過Module中的方法進行提供,比如provideUserStore()
//2)通過類的構造函數進行提供對象,註釋掉上面的provideUserStore()方法
//3)代碼執行順序:創建參數對象的方法先執行,比如構造;
@Provides
UserManager provideUserManager(UserStore userStore) {
return new UserManager(userStore);
}
}
package com.example.administrator.testdaggger2;
import android.util.Log;
import javax.inject.Inject;
/**
* Created on 2017/5/9.
* Author:crs
* Description:UserStore 用戶數據存儲
*/
public class UserStore {
//通過構造函數提供依賴
@Inject
public UserStore() {
}
private static final String TAG = "UserStore";
public void register(){
Log.i(TAG,"測試數據");
}
}
———————————————————————————————————————>
模塊化開發:自定義module之間相互include,component之間相互依賴
通過@Named @Qualifier:區別不同對象的實例
同一個類,可能要創建兩個對象,處理不同的業務邏輯
通過類型進行注入,根據@Inject標記的變量類型ApiService,在Module中尋找返回值爲ApiService的方法進行調用。但是如果Module中有多個方法,它們的返回值都爲ApiService,那麼就需要使用@Named註解用於區別。(區分不同對象的實例@Qualifier)
比如:訪問測試服務器,訪問正式服務器
代碼如下:
package com.example.administrator.testdragger2.dagger2;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.example.administrator.testdragger2.R;
import javax.inject.Inject;
import javax.inject.Named;
/**
* Created on 2017/5/9.
* Author:crs
* Description:TestMainActivity
*/
public class TestMainActivity extends AppCompatActivity {
private static final String TAG ="TestMainActivity" ;
//訪問測試服務器
@Named("dev")
@Inject
ApiService apiServiceDev;
//訪問正式服務器
@Named("release")
@Inject
ApiService apiServiceRelease;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
DaggerUserComponent.builder().httpModule(new HttpModule()).userModule(new UserModule(this)).build().inject(this);
//此時這兩個兩個對象的內存地址是不一樣的
Log.i(TAG,apiServiceDev.toString());
Log.i(TAG,apiServiceRelease.toString());
//apiServiceDev.register();
//apiServiceRelease.register();
}
}
Component連接兩個Module(可以連接多個Module)
package com.example.administrator.testdragger2.dagger2;
import dagger.Component;
/**
* Created on 2017/5/9.
* Author:crs
* Description:UserComponent
*/
@Component(modules={UserModule.class,HttpModule.class})
public interface UserComponent {
void inject(TestMainActivity activity);
}
UserModule包含HttpModule
package com.example.administrator.testdragger2.dagger2;
import android.content.Context;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
import okhttp3.OkHttpClient;
/**
* Created on 2017/5/9.
* Author:crs
* Description:自定義Module類
*/
//表示當前module引用HttpModule,進而提供OkHttpClient的對象
@Module(includes = {HttpModule.class})
public class UserModule {
private Context mContext;
UserModule(Context context) {
this.mContext=context;
}
//此時缺少OkHttpClient的實例,並且當前自定義Module中並沒有提供,如何處理?
@Named("dev")
@Provides
ApiService provideApiServiceDev(OkHttpClient client){
return new ApiService(client);
}
@Named("release")
@Provides
ApiService provideApiServiceRelease(OkHttpClient client){
return new ApiService(client);
}
}
package com.example.administrator.testdragger2.dagger2;
import java.io.IOException;
import javax.inject.Inject;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* Created on 2017/5/9.
* Author:crs
* Description:ApiService網絡請求
*/
public class ApiService {
//常用類:OKHttpClient,Request,RequestBody,CallBack
OkHttpClient client;
//構造函數
@Inject
public ApiService(OkHttpClient client) {
this.client=client;
}
//主要用於網絡請求
public void register(){
RequestBody body=RequestBody.create(null,"");
Request request = new Request.Builder()
.url("")
.post(body)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
}
———————————————————————————————————————>