Dagger2
Dagger是一個完全靜態(tài)的,在編譯時進行依賴注入的框架,原來是由Square公司維護的然后現(xiàn)在把這堆東西扔給Google維護了。Dagger解決了基于反射帶來的開發(fā)和性能上的問題(因為Dagger并沒有用反射來做依賴注入)說了那么多,其實就是告訴我們這家伙可以用來做依賴注入哦。
依賴注入:我們在做項目時,經(jīng)常需要在一個對象里去創(chuàng)建另一個對象的實例,這種行為是產(chǎn)生耦合的常見形式,對于一個大型項目來說,過多的相互依賴會導(dǎo)致代碼難以維護,很容易就會碰到修改一個小需求需要大面積的修改各種代碼,特別是代碼原來不是自己維護的,擼著代碼的你就開始問候別人家的親友了。
在需要依賴的類中不要通過new來創(chuàng)建依賴而是通過方法提供的參數(shù)注入進來,這樣我們的需要依賴的類和提供依賴的類的實現(xiàn)方法分隔開了,一切又變得如此美好咯。
dagger2是一個依賴注入框架,在編譯期間自動生成代碼,負責(zé)依賴對象的創(chuàng)建。
用dagger2提供依賴有什么好處:為了進一步解耦和方便測試,我們會使用依賴注入的方式構(gòu)建對象 (不使用 new 來創(chuàng)建依賴對象)。在mvp中,presenter層會持有view和model層的依賴,依賴注入主要用于解耦,通過依賴注入創(chuàng)建對象,不再使用new來創(chuàng)建對象。
依賴注入的目的是:給你提供一個對象依賴。
Dagger2的常用注解:?
@Inject:此注解用于告訴Dagger2,我們需要這個類的實例對象。主要用于標記哪個類是需要注入的。
@Module:此注解里面全是方法,用于對外提供對象,自己定義方法,方法上使用@Provides。自定義一個類,以Module結(jié)尾,用@Module注解。
@Provides:此注解用于標記方法,表示可以通過這個方法獲取一個對象,一般用于自定義類中。
@Component:此注解主要用于關(guān)聯(lián)自定義module類和MainActivity;關(guān)聯(lián)module使用:@Component(modules={UserModule.class});關(guān)聯(lián)Activity,以方法參數(shù)的形式傳入MainActivity到連接器中
@Named與@Qualifier:用于區(qū)別不同對象的實例。必須要成對出現(xiàn),否則會報錯。
@PerActivity:限定對象的生命周期和Activity一樣。一般應(yīng)用于自定義的Component上。
@Singleton:標記為單例模式,如果在自定義Module中使用了此注解,在自定義的Component上也要使用該注解。
?
使用方式:
1)自定義Module,里面的方法用于提供依賴,
2)自定義Component接口,里面全是Activity的注入方法,
3)按Ctrl+F9進行編譯。
?
?
自定義Module類:
自定義module中的方法 要以provide開頭
通過構(gòu)造方法傳遞Context
?
如果定義的module,需要傳參數(shù),就需要在Activity使用build進行諸如
?
?
添加依賴:
//添加依賴 compile 'com.google.dagger:dagger:2.9' annotationProcessor 'com.google.dagger:dagger-compiler:2.9'MainActivity代碼:此依賴注入的目的是獲取ApiService類的實例,然后調(diào)用其中的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會自動創(chuàng)建這個類,以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,要不然會出現(xiàn)空指針。 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() { //請求網(wǎng)絡(luò)數(shù)據(jù) Log.i(TAG,"測試數(shù)據(jù)"); } }如果自定義類module中的方法,需要一個對象參數(shù),怎么處理?需要一個方法去提供這個對象。
1)在類的構(gòu)造方法上添加@Inject注解
2)自己寫一個方法去提供參數(shù)對象
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中的方法中需要參數(shù)對象怎么處理?(構(gòu)造函數(shù)、自己提供方法) //Dagger會自動創(chuàng)建這個類,以Dagger開頭+UserComponent,編譯時注入,按Ctrl+F9編輯即可 //DaggerUserComponnent.create().inject(this); //userManager.register(); //Dagger的關(guān)系非常簡單,MainActivity中需要對象,那么就在Module中提供對象;而他們之間的橋梁就是componnent //自定義類Module的構(gòu)造方法中需要傳入一個上下文對象,那么在MainActivity中就需要傳遞進去。 //使用下面的這種方式進行參數(shù)傳遞: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中的方法需要對象參數(shù),怎么處理? //1)通過Module中的方法進行提供,比如provideUserStore() //2)通過類的構(gòu)造函數(shù)進行提供對象,注釋掉上面的provideUserStore()方法 //3)代碼執(zhí)行順序:創(chuàng)建參數(shù)對象的方法先執(zhí)行,比如構(gòu)造; @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 用戶數(shù)據(jù)存儲 */ public class UserStore { //通過構(gòu)造函數(shù)提供依賴 @Inject public UserStore() { } private static final String TAG = "UserStore"; public void register(){ Log.i(TAG,"測試數(shù)據(jù)"); } }模塊化開發(fā):自定義module之間相互include,component之間相互依賴
通過@Named @Qualifier:區(qū)別不同對象的實例
同一個類,可能要創(chuàng)建兩個對象,處理不同的業(yè)務(wù)邏輯
通過類型進行注入,根據(jù)@Inject標記的變量類型ApiService,在Module中尋找返回值為ApiService的方法進行調(diào)用。但是如果Module中有多個方法,它們的返回值都為ApiService,那么就需要使用@Named注解用于區(qū)別。(區(qū)分不同對象的實例@Qualifier)
比如:訪問測試服務(wù)器,訪問正式服務(wù)器
代碼如下:
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" ; //訪問測試服務(wù)器 @Named("dev") @Inject ApiService apiServiceDev; //訪問正式服務(wù)器 @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); //此時這兩個兩個對象的內(nèi)存地址是不一樣的 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網(wǎng)絡(luò)請求 */ public class ApiService { //常用類:OKHttpClient,Request,RequestBody,CallBack OkHttpClient client; //構(gòu)造函數(shù) @Inject public ApiService(OkHttpClient client) { this.client=client; } //主要用于網(wǎng)絡(luò)請求 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 { } }); } }
轉(zhuǎn)載于:https://www.cnblogs.com/foxy/p/7850431.html
總結(jié)