第一部分
dagger2是一個(gè)依賴注入的框架,舉個(gè)例子如果我們不適用dagger注入窜护,我們調(diào)用一個(gè)對象必須使用構(gòu)造方法效斑,這樣就會造成了類與類的組合,但dagger的使用解決了這一問題柱徙。
這是dagger的官網(wǎng)
我們看一下跟dagger相關(guān)的概念缓屠,
@Inject
通常在需要依賴的地方使用這個(gè)注解奇昙。換句話說,你用它告訴Dagger這個(gè)類或者字段需要依賴注入敌完。這樣储耐,Dagger就會構(gòu)造一個(gè)這個(gè)類的實(shí)例并滿足他們的依賴。 官方點(diǎn)說就是帶有此注解的屬性或構(gòu)造方法將參與到依賴注入中蠢挡,Dagger2會實(shí)例化有此注解的類弧岳。
@Module
Modules類里面的方法專門用來提供依賴,他就像一個(gè)工廠一樣去生產(chǎn)需要添加依賴的實(shí)例业踏。所以我們定義一個(gè)類禽炬,用@Module來注解,這樣Dagger在構(gòu)造類的實(shí)例的時(shí)候勤家,就知道從哪里去找到需要的依賴腹尖。modules的一個(gè)重要特性是它們設(shè)計(jì)為分區(qū)并組合在一起(例如,我們的app中可以有多個(gè)組成在一起的modules)伐脖。它里面定義一些用@Provides注解的以provide開頭的方法热幔,這些方法就是所提供的依賴,Dagger2會在該類中尋找實(shí)例化某個(gè)類所需要的依賴讼庇。
@Provides
上面引入了這個(gè)概念了绎巨。在modules中,我們定義的方法是用@Provides這個(gè)注解蠕啄,以此來告訴Dagger我們想要構(gòu)造對象并提供這些依賴场勤。
@Component
Components從根本上來說他就是一個(gè)注入器,也可以說是用來將@Inject和@Module聯(lián)系起來的橋梁歼跟,它的主要作用就是連接這兩個(gè)部分和媳。Components可以提供所有定義了的類型的實(shí)例(inject需要),比如:我們必須用@Component注解一個(gè)接口然后列出所有的 哈街。功能是從@Module中獲取依賴并將依賴注入給@Inject
dagger必不可少的三個(gè)元素:Module,Component,Container
這里有張圖來說明它們之間的關(guān)系留瞳。
第二部分 Dagger2的基本使用(上)
下面我們看下具體怎么使用
首先要導(dǎo)入依賴
dependencies {
implementation 'com.google.dagger:dagger:2.16'
annotationProcessor 'com.google.dagger:dagger-compiler:2.16'}
這里有個(gè)ApiService的類,我們需要在MainActivity中使用它的實(shí)例骚秦,如果我們不用dagger她倘,我們就只能new ApiService()
,但是我們現(xiàn)在使用dagger,就不需要new了作箍。
先看下ApiService這個(gè)沒用的類
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
public void register() {
Log.i("zhang_xin","register成功");
}
}
等下我們要使用dagger獲取它的實(shí)例帝牡。
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
ApiService mApiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
在MainActivity里我們使用@inject注解,告訴dagger,我需要ApiService的實(shí)例蒙揣。dagger就會從@Component注釋的接口中尋找ApiService的實(shí)例,那好开瞭,我們下面創(chuàng)建這個(gè)接口懒震。
package com.example.dagger2test;
import dagger.Component;
@Component(modules = {罩息?.class})//關(guān)聯(lián)到module
public interface UserComponet {
}
大家看下Component的源碼
public @interface Component {
/**
* A list of classes annotated with {@link Module} whose bindings are used to generate the
* component implementation. Note that through the use of {@link Module#includes} the full set of
* modules used to implement the component may include more modules that just those listed here.
*/
Class<?>[] modules() default {};
/**
* A list of types that are to be used as <a href="#component-dependencies">component
* dependencies</a>.
*/
Class<?>[] dependencies() default {};
可以發(fā)現(xiàn),Component需要module,我們需要在?處傳入我們的module
下面我們創(chuàng)建module
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
public class UseModule {
@Provides//提供依賴
public ApiService provideApiService(){
return new ApiService();
}
}
在module里我們真正創(chuàng)建ApiService的實(shí)例个扰,這個(gè)提供ApiService實(shí)例的方法瓷炮,我們需要標(biāo)注為@provides
我們現(xiàn)在重新捋一下我們的思路
在MainActivity(就是圖中Container)中,我們需要ApiService的實(shí)例递宅,我們在ApiService上加上@inject注解娘香,這樣dagger就知道我們需要ApiService的實(shí)例,dagger就會去@Component注解下的類去找該實(shí)例办龄,commponent是一個(gè)橋梁烘绽,它關(guān)聯(lián)了很多modules。我們看下@Component的代碼
package com.example.dagger2test;
import dagger.Component;
@Component(modules = {UseModule.class})
public interface UserComponet {
}
注意俐填,以上只是Module與Component進(jìn)行了關(guān)聯(lián)安接,我說過Component是一個(gè)橋梁,所我們還需要把Component與MainActivity進(jìn)行關(guān)聯(lián)英融,
package com.example.dagger2test;
import dagger.Component;
@Component(modules = {UseModule.class})//關(guān)聯(lián)到module
public interface UserComponet {
void inject(MainActivity activity);//關(guān)聯(lián)到Activity
}
從這行注釋@Component(modules = {UseModule.class})
,dagger就知道要去UseModule里獲取ApiService的實(shí)例。
我們在看下UseModele類奏赘,在這個(gè)類里獲取ApiService的實(shí)例竹揍,注意,該類需要添加@module
注解痕鳍。提供對象的方法添加@Prividers
,方法的返回值為ApiService且有@Provides注釋硫豆,那么dagger就會從這個(gè)方法里獲取ApiService對象
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides//提供依賴
public ApiService provideApiService(){
return new ApiService();
}
}
到這里我們在MainActivity(Container)里調(diào)用ApiService實(shí)例的代碼就全部完成了。然后我們r(jià)ebuild我們的工程
這個(gè)時(shí)候dagger會自動(dòng)生成DaggerUserComponet類额获,該類有個(gè)create()
,會生成UserComponet的實(shí)例够庙,然后通過該實(shí)例我們調(diào)用UserComponet的inject方法。完整代碼如下
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
/**
* 依賴注入框架抄邀,解決繁瑣的依賴關(guān)系
* 必不可少的三種元素:Module,Component,Container,module提供依賴的集合耘眨,里面有很多方法是提供依賴的
* ,component
*/
public class MainActivity extends AppCompatActivity {
@Inject//dagger會從commponent里去找ApiService的實(shí)例境肾。使用依賴
ApiService mApiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//生成UserComponet的實(shí)例剔难,調(diào)用inject()
DaggerUserComponet.create().inject(this);
mApiService.register();
}
}
運(yùn)行會輸出
10-20 15:22:10.585 22065-22065/com.example.dagger2test I/zhang_xin: register成功
為了方便大家看,我把所有相關(guān)的類在貼一遍奥喻。
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
public void register() {
Log.i("zhang_xin","register成功");
}
}
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject//dagger會從commponent里去找ApiService的實(shí)例偶宫。使用依賴
ApiService mApiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.create().inject(this);
mApiService.register();
}
}
package com.example.dagger2test;
import dagger.Component;
@Component(modules = {UseModule.class})//關(guān)聯(lián)到module
public interface UserComponet {
void inject(MainActivity activity);//關(guān)聯(lián)到Activity
}
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides//提供依賴
public ApiService provideApiService(){
return new ApiService();
}
}
第三部分 Dagger2的基本使用(下)
我們再來看一下復(fù)雜的例子。
我們需要MainActivity類里獲取UserManager實(shí)例环鲤,UserManager的構(gòu)造方法需要傳入另外兩個(gè)類的實(shí)例纯趋。我們看下UserManager類
package com.example.dagger2test;
public class UserManager {
private ApiService apiService;
private UserStore userStore;
public UserManager(ApiService apiService, UserStore userStore) {
this.apiService = apiService;
this.userStore = userStore;
}
public void register(){
apiService.register();
userStore.register();
}
}
這是UserStore類
package com.example.dagger2test;
import android.util.Log;
public class UserStore {
public void register(){
Log.i("zhang_xin","UserStore注冊成功");
}
}
我們有兩種方法
第一種,修改UseModule
文件
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides
public ApiService getApiService() {
return new ApiService();
}
@Provides
public UserStore getUserStore() {
return new UserStore();
}
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
然后在MainActivity中調(diào)用用
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.create().inject(this);
userManager.register();
}
}
看下打印輸出結(jié)果
10-20 17:03:03.092 27717-27717/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注冊成功
第二種方法,使用構(gòu)造方法吵冒。
我們先把UseModule中方法注釋掉
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
// @Provides
// public ApiService getApiService() {
// return new ApiService();
// }
//
// @Provides
// public UserStore getUserStore() {
// return new UserStore();
// }
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
然后修改ApiService和UseModule兩個(gè)類纯命,添加@Inject注釋的方法。
package com.example.dagger2test;
import android.util.Log;
import javax.inject.Inject;
public class UserStore {
@Inject
public UserStore(){
}
public void register(){
Log.i("zhang_xin","UserStore注冊成功");
}
}
package com.example.dagger2test;
import android.util.Log;
import javax.inject.Inject;
public class ApiService {
@Inject
public ApiService() {
}
public void register() {
Log.i("zhang_xin", "ApiService register成功");
}
}
運(yùn)行MainActivity
10-20 17:14:14.795 28228-28228/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注冊成功
由以上兩種方法我們可以得出結(jié)論痹栖。
如果Module中沒有提供@Providers注釋的方法亿汞,Dagger會去調(diào)用@Inject注釋的方法。
第四部分
我們現(xiàn)在有這么個(gè)需求揪阿,那就是UseModule的構(gòu)造方法需要傳入?yún)?shù)疗我。我們修改下UseModule類
package com.example.dagger2test;
import android.content.Context;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
private Context context;
public UseModule (Context context){
this.context=context;
}
@Provides
public ApiService getApiService() {
return new ApiService();
}
@Provides
public UserStore getUserStore() {
return new UserStore(this.context);
}
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
現(xiàn)在大家看下,我們怎么在MainActivity類里調(diào)用
DaggerUserComponet.create().inject(this);
肯定是行不通了
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule(this)).build().inject(this);
userManager.register();
}
}
第五部分
假設(shè)我們現(xiàn)在有這么一個(gè)需求南捂,ApiService里需要傳入一個(gè)參數(shù)(實(shí)際開發(fā)中可能是OkHttpClient等吴裤,我們這里只簡單的使用Dog),我們可以這么做
黑毅,先看下Dog類
package com.example.dagger2test;
public class Dog {
}
看下UserManager類
package com.example.dagger2test;
public class UserManager {
private ApiService apiService;
private UserStore userStore;
public UserManager(ApiService apiService, UserStore userStore) {
this.apiService = apiService;
this.userStore = userStore;
}
public void register(){
apiService.register();
userStore.register();
}
}
看下ApiService類
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
private Dog dog;
//注意 dog是單例對象
public ApiService(Dog dog) {
this.dog = dog;
}
public void register() {
Log.i("zhang_xin", "ApiService register成功");
}
}
我們可以單獨(dú)寫一個(gè)針對Dog類的DogModule
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class DogModule {
@Singleton//增加單例注釋
@Provides
public Dog getUser(){
return new Dog();
}
}
然后在UseModule中引用DogMoudle
package com.example.dagger2test;
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
//includes引入另外一個(gè)module
@Module(includes = {DogModule.class})
public class UseModule {
@Provides
public ApiService getApiService(Dog dog) {
Log.i("zhang_xin", "dog是否是單例:" + dog.toString());
return new ApiService(dog);
}
@Provides
public UserStore getUserStore() {
return new UserStore();
}
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
同時(shí)UserComponet也需要修改
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
//增加單例注釋
@Singleton
@Component(modules = {UseModule.class})//關(guān)聯(lián)到module
public interface UserComponet {
void inject(MainActivity activity);//關(guān)聯(lián)到Activity
}
下面我們在MainActivity中調(diào)用
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule()).dogModule(new DogModule()).build().inject(this);
userManager.register();
}
}
最后我們看一下打印輸出
10-20 20:23:15.805 31622-31622/com.example.dagger2test I/zhang_xin: dog是否是單例:com.example.dagger2test.Dog@b45757d 10-20 20:23:15.809 31622-31622/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注冊成功
多次打印都是這個(gè)值:com.example.dagger2test.Dog@b45757d嚼摩;
說明Dog確實(shí)是單例模式
除此之外還有一種方法,我們首先把UseModule恢復(fù)原來的樣子
package com.example.dagger2test;
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
//這里刪除includes
@Module
public class UseModule {
@Provides
public ApiService getApiService(Dog dog) {
Log.i("zhang_xin", "dog是否是單例:" + dog.toString());
return new ApiService(dog);
}
@Provides
public UserStore getUserStore() {
return new UserStore();
}
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
然后修改我們的UserComponet類
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
//增加DogModule.class
@Component(modules = {UseModule.class,DogModule.class})//關(guān)聯(lián)到module
public interface UserComponet {
void inject(MainActivity activity);//關(guān)聯(lián)到Activity
}
其余的代碼不變矿瘦,效果一樣
第六部分 創(chuàng)建和區(qū)分不同實(shí)例(上)
我們現(xiàn)在有新的需求了枕面,我們在MainActivity里需要兩個(gè)ApiService對象,該怎么操作呢缚去?其實(shí)也很簡單潮秘,只需要在UseModule中提供兩個(gè)@Provides注釋的方法,同時(shí)在MainActivity和UseModule中添加@Named注釋易结,注意MainActivity中的@Named和UseModule中的@Named字段要一一對應(yīng)枕荞。看下代碼更一目了然
ApiService類
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
public void register() {
Log.i("zhang_xin", "ApiService register成功");
Log.i("zhang_xin",this.toString());
}
}
MainActivity需要兩個(gè)ApiService類,每個(gè)對象前添加@Named注釋
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
import javax.inject.Named;
public class MainActivity extends AppCompatActivity {
@Named("1")
@Inject
ApiService apiService1;
@Inject
@Named("2")
ApiService apiService2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
apiService1.register();
apiService2.register();
}
}
UseNodule類搞动,添加@Named注釋與MainActivity一一對應(yīng)
package com.example.dagger2test;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides
@Named("1")
public ApiService getApiService1(Dog dog) {
return new ApiService();
}
@Provides
@Named("2")
public ApiService getApiService2(Dog dog) {
return new ApiService();
}
}
看下打印輸出
10-22 19:44:09.799 31505-31505/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d 10-22 19:44:09.800 31505-31505/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@20d4c72
可以看出兩個(gè)ApiService的內(nèi)存地址不一樣躏精,是兩個(gè)不同的對象。
注意鹦肿,如果我們不添加@Named注釋矗烛,dagger會根據(jù)返回值類型進(jìn)行匹配。
第七部分 dagger創(chuàng)建和區(qū)分不同實(shí)例(下)
上接第六部分箩溃,第六部分的功能我們還可以這樣實(shí)現(xiàn)瞭吃,自定義@Interface
我們首先自定義兩個(gè)@Interface文件,一個(gè)叫@First涣旨,一個(gè)叫@Second
package com.example.dagger2test;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface First {
}
package com.example.dagger2test;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Second {
}
在UseModule和MainActivity中歪架,我們需要把@Named注釋分別改為@First和@Second,我們看下代碼
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
import javax.inject.Named;
public class MainActivity extends AppCompatActivity {
@First
@Inject
ApiService apiService1;
@Second
@Inject
ApiService apiService2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
apiService1.register();
apiService2.register();
}
}
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides
@First
public ApiService getApiService1() {
return new ApiService();
}
@Provides
@Second
public ApiService getApiService2() {
return new ApiService();
}
}
看下運(yùn)行效果
10-22 19:59:50.668 32434-32434/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d ApiService register成功 10-22 19:59:50.669 32434-32434/com.example.dagger2test I/zhang_xin: com.example.dagger2test.ApiService@20d4c72
第八部分:Singleton 單例講解(上)
我們需要ApiService是單例模式
首先我們看下ApiService類
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
public void register() {
Log.i("zhang_xin", "ApiService register成功");
Log.i("zhang_xin",this.toString());
}
}
這個(gè)時(shí)候我們需要在Module類的方法中添加@Singleton注釋霹陡,代碼如下
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Singleton
@Provides
public ApiService getApiService() {
return new ApiService();
}
}
注意我們現(xiàn)在需要修改UserComponent類和蚪,他的類也需要添加@Singleton注釋
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
@Singleton//因?yàn)閁seModule添加了該注釋止状,所以這里也需要添加注釋
@Component(modules = {UseModule.class,DogModule.class})//關(guān)聯(lián)到module
public interface UserComponet {
void inject(MainActivity activity);//關(guān)聯(lián)到Activity
}
然后我們看下MainActivity
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
import javax.inject.Named;
public class MainActivity extends AppCompatActivity {
@Inject
ApiService apiService1;
@Inject
ApiService apiService2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
apiService1.register();
apiService2.register();
}
}
我們多次運(yùn)行都會打印這個(gè)結(jié)果
10-22 20:33:15.896 3145-3145/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d ApiService register成功 com.example.dagger2test.ApiService@b45757d
apiService1和apiService2內(nèi)存地址一樣,說明它們是同一個(gè)對象惠呼。
第八部分:Singleton 單例講解(下)
我們第七部分實(shí)現(xiàn)了單例模式导俘,但是這種方法實(shí)現(xiàn)的單例模式是有問題的,如果我們現(xiàn)在在創(chuàng)建一個(gè)MainActivity2和與之相關(guān)的@Component注釋的類剔蹋,那么這個(gè)時(shí)候我們無法保證兩個(gè)Activity中的ApiService是同一個(gè)。其實(shí)大家翻翻Dagger的源碼就會發(fā)現(xiàn)辅髓,Dagger的單例模式必須要保證是同一個(gè)@Component注釋的類泣崩。
我們先看這樣的一個(gè)例子,我們把訪問網(wǎng)絡(luò)的類CallNets設(shè)置為單例模式
這個(gè)是ApiService類洛口,他里面有一個(gè)CallNets類矫付,這個(gè)類是單例模式。
package com.example.daggertest2;
import android.util.Log;
public class ApiService {
private CallNets callNets;
public ApiService(CallNets callNets) {
this.callNets = callNets;
}
public void register() {
Log.i("zhang_xin", "apiService注冊成功");
}
}
CallNets類第焰,實(shí)際開發(fā)中可能是OkhttpClient等买优。
package com.example.daggertest2;
public class CallNets {
//訪問網(wǎng)絡(luò)的邏輯
}
CallNetsModule類,方法我們注解成單例模式
package com.example.daggertest2;
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class CallNetsModule {
@Singleton
@Provides
public CallNets getCallNets(){
CallNets callNets=new CallNets();
Log.i("zhang_xin",callNets.toString());
return callNets;
}
}
接下來我們創(chuàng)建了兩個(gè)@Component注解的類
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules=UserModule.class)
public interface LoginComponet {
void inject(LoginActivity activity);
}
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = UserModule.class)
public interface UserComponet {
void inject(MainActivity activity);
}
UserModule和UserManager
package com.example.daggertest2;
public class UserManager {
private ApiService apiService;
public UserManager(ApiService apiService){
this.apiService=apiService;
}
public void register(){
apiService.register();
}
}
package com.example.daggertest2;
import dagger.Module;
import dagger.Provides;
@Module(includes = {CallNetsModule.class})
public class UserModule {
@Provides
public ApiService getApiService(CallNets callNets){
return new ApiService(callNets);
}
@Provides
public UserManager getUserManager(ApiService apiService){
return new UserManager(apiService);
}
}
兩個(gè)Activity
package com.example.daggertest2;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().userModule(new UserModule()).callNetsModule(new CallNetsModule()).build().inject(this);
userManager.register();
startActivity(new Intent(this,LoginActivity.class));
}
}
package com.example.daggertest2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class LoginActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
DaggerLoginComponet.builder().userModule(new UserModule()).callNetsModule(new CallNetsModule()).build().inject(this);
userManager.register();
}
}
我們看下打印輸出
/zhang_xin: com.example.daggertest2.CallNets@b45757d /zhang_xin: apiService注冊成功 /zhang_xin: com.example.daggertest2.CallNets@eea8d0f /zhang_xin: apiService注冊成功
很明顯挺举,兩個(gè)CallNets不是同一個(gè)對象杀赢,我們雖然標(biāo)注了@Singleton,但因?yàn)閯?chuàng)建了兩個(gè)Componet,所以得到的是兩個(gè)不同的CallNets對象湘纵。
接下來我們就解決這個(gè)問題脂崔。
我們需要?jiǎng)?chuàng)建一個(gè)最高級別的Component
首先我們把CallNetsModule中無法提供單例的方法注釋掉
package com.example.daggertest2;
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class CallNetsModule {
// @Singleton
// @Provides
// public CallNets getCallNets(){
// CallNets callNets=new CallNets();
// Log.i("zhang_xin",callNets.toString());
// return callNets;
// }
}
然后我們創(chuàng)建AppComponet和AppModule
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = AppModule.class)
public interface AppComponet {
//這里不需要提供inject方法,因?yàn)槲覀儾恍枰⑷胛嗯纾且栏接谄渌腃onmponent
}
我們在AppModule類中提供CallNets的單例
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AppModule {
@Singleton
@Provides
public CallNets getCallNets(){
CallNets callNets=new CallNets();
Log.i("zhang_xin",callNets.toString());
return callNets;
}
}
然后修改LoginComponent UserComponent
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
/**
* 1,在這里我解釋下砌左,我們的UserModule并沒有提供CallNets實(shí)例,如果Dagger在UserModule中沒有發(fā)現(xiàn)CallNets實(shí)例
* 他就會去依賴既AppComponet.class里面去找.
* 2,這里不能有@Singleton注釋铺敌,因?yàn)镃omponent的dependencies與Component
* 自身的scope不能相同
*/
@Component(modules=UserModule.class,dependencies = AppComponet.class)
public interface LoginComponet {
void inject(LoginActivity activity);
}
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
/**
* 2,這里不能有@Singleton注釋汇歹,因?yàn)镃omponent的dependencies與Component
* 自身的scope不能相同
*/
@Component(modules = UserModule.class,dependencies = AppComponet.class)
public interface UserComponet {
void inject(MainActivity activity);
}
這里我做下說明
注意第五點(diǎn),所以我們沒辦法給LoginComponent和AppComponent添加@Singleton注釋偿凭,既然沒辦法添加@Singleton注釋产弹,那么我們該怎么給LoginComponent和AppComponent添加注釋呢?因?yàn)镈agger給我們提供的注釋只有@Singleton笔喉,所以需要我們自己定義注釋取视。
package com.example.daggertest2;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Scope;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Scope
@Documented
@Retention(RUNTIME)
public @interface ActivityScope {
}
@scope注明是Scope
@documented標(biāo)記在文檔
@Retention 級別,有source class runtime
然后我們修改LoginComponent和UserComponent文件常挚,添加@ActivityScope 注釋作谭。
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
/**
* 1,在這里我解釋下,我們的UserModule并沒有提供CallNets實(shí)例奄毡,如果Dagger在UserModule中沒有發(fā)現(xiàn)CallNets實(shí)例
* 他就會去依賴既AppComponet.class里面去找.
* 2,這里不能有@Singleton注釋折欠,因?yàn)镃omponent的dependencies與Component
* 自身的scope不能相同
*/
@ActivityScope//添加該注釋
@Component(modules=UserModule.class,dependencies = AppComponet.class)
public interface LoginComponet {
void inject(LoginActivity activity);
}
package com.example.daggertest2;
import dagger.Component;
/**
* 2,這里不能有@Singleton注釋,因?yàn)镃omponent的dependencies與Component
* 自身的scope不能相同
*/
@ActivityScope//添加該注釋
@Component(modules = UserModule.class,dependencies = AppComponet.class)
public interface UserComponet {
void inject(MainActivity activity);
}
然后修改AppComponent類
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = AppModule.class)
public interface AppComponet {
Conmponent
CallNets getCallNets();
}
在這里我們做一個(gè)橋接,這里的CallNets對象就是由AppModule提供的锐秦。
我們現(xiàn)在reBuild工程咪奖,已經(jīng)可以了沒有報(bào)錯(cuò)
可是我們現(xiàn)在又面臨一個(gè)問題,接下來我們該怎樣在LoginActivity和MainActivity中使用AppComponent呢酱床?
DaggerUserComponet.builder().userModule(new UserModule()).appComponet();
我們可以看到appComponent()需要傳入AppComponet類型的對象羊赵,在這里我們怎么給appComponent()傳入?yún)?shù)呢?
因?yàn)镾ingleton是application級別的扇谣,所以我們需要在Application中將AppComponent實(shí)例化昧捷。創(chuàng)建MyApplication繼承Application。
package com.example.daggertest2;
import android.app.Application;
import android.util.Log;
public class MyApplication extends Application {
private AppComponet appComponet;
@Override
public void onCreate() {
super.onCreate();
appComponet= DaggerAppComponet.create();
}
public AppComponet getAppComponet() {
return appComponet;
}
}
然后我們就可以在MainActivity 和LoginActivity里調(diào)用了
package com.example.daggertest2;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().userModule(new UserModule())
.appComponet(((MyApplication) getApplication())
.getAppComponet()).build().inject(this);
userManager.register();
startActivity(new Intent(this, LoginActivity.class));
}
}
package com.example.daggertest2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class LoginActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
DaggerLoginComponet.builder().userModule(new UserModule())
.appComponet(((MyApplication) getApplication())
.getAppComponet()).build().inject(this);
userManager.register();
}
}
這樣我們就實(shí)現(xiàn)了單例模式
我們在ApiService中添加打印數(shù)據(jù)罐寨,測試下是不是單例模式
package com.example.daggertest2;
import android.util.Log;
public class ApiService {
private CallNets callNets;
public ApiService(CallNets callNets) {
this.callNets = callNets;
}
public void register() {
Log.i("zhang_xin", "apiService注冊成功"+this.callNets.toString());
}
}
看下打印結(jié)果
10-24 16:22:59.691 2967-2967/com.example.daggertest2 I/zhang_xin: apiService注冊成功com.example.daggertest2.CallNets@4a7ac880
10-24 16:22:59.701 2967-2967/com.example.daggertest2 I/zhang_xin: apiService注冊成功com.example.daggertest2.CallNets@4a7ac880
OK靡挥,大功告成!
第九部分:一個(gè)Commponent關(guān)聯(lián)兩個(gè)Module
兩個(gè)Object類鸯绿,要通過注入獲取實(shí)例的類
package com.example.dagger2test;
/**
* @author writing
* @time 2019/10/25 21:29
* @note
*/
public class DatabaseObject {
}
package com.example.dagger2test;
/**
* @author writing
* @time 2019/10/25 21:29
* @note
*/
public class HttpObject {
}
兩個(gè)module類
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/25 21:28
* @note
*/
@Module
public class DatabaseModule {
@Provides
public DatabaseObject providerHttpObject(){
return new DatabaseObject();
}
}
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/25 21:28
* @note
*/
@Module
public class HttpModule {
@Provides
public HttpObject providerHttpObject(){
return new HttpObject();
}
}
component類
package com.example.dagger2test;
import dagger.Component;
/**
* @author writing
* @time 2019/10/25 21:33
* @note
*/
@Component(modules = {HttpModule.class,DatabaseModule.class})
public interface MyComponent {
void injectMainActivity(MainActivity mainActivity);
}
在MainActivity中的使用
package com.example.dagger2test;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
HttpObject httpObject;
@Inject
DatabaseObject databaseObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMyComponent.create().injectMainActivity(this);
Log.i("zhang_xin",httpObject.hashCode()+"");
Log.i("zhang_xin",databaseObject.hashCode()+"");
}
}
第十部份:全局單例的另一種方式
創(chuàng)建MyApplication,在application中注入
兩個(gè)通過注入獲取對象的類
package com.example.dagger2test;
/**
* @author writing
* @time 2019/10/25 21:29
* @note
*/
public class DatabaseObject {
}
package com.example.dagger2test;
/**
* @author writing
* @time 2019/10/25 21:29
* @note
*/
public class HttpObject {
}
對應(yīng)的module
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/25 21:28
* @note
*/
@Module
public class DatabaseModule {
@Provides
public DatabaseObject providerHttpObject(){
return new DatabaseObject();
}
}
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/25 21:28
* @note
*/
@Singleton
@Module
public class HttpModule {
@Singleton
@Provides
public HttpObject providerHttpObject(){
return new HttpObject();
}
}
component類
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
/**
* @author writing
* @time 2019/10/25 21:33
* @note
*/
@Singleton
@Component(modules = {HttpModule.class,DatabaseModule.class})
public interface MyComponent {
void injectMainActivity(MainActivity mainActivity);
void injectSecondActivity(SecondActivity secondActivity);
}
Application
package com.example.dagger2test;
import android.app.Application;
/**
* @author writing
* @time 2019/10/25 21:51
* @note
*/
public class MyApplication extends Application {
private MyComponent myComponent;
@Override
public void onCreate() {
super.onCreate();
myComponent = DaggerMyComponent.builder().httpModule(new HttpModule()).build();
}
public MyComponent getAppComponent(){
return myComponent;
}
}
兩個(gè)Activity
package com.example.dagger2test;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
HttpObject httpObject;
@Inject
HttpObject httpObject2;
@Inject
DatabaseObject databaseObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((MyApplication)getApplication()).getAppComponent().injectMainActivity(this);
Log.i("zhang_xin",httpObject.hashCode()+"");
Log.i("zhang_xin",httpObject2.hashCode()+"");
Log.i("zhang_xin",databaseObject.hashCode()+"");
findViewById(R.id.textView).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
}
}
package com.example.dagger2test;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
public class SecondActivity extends AppCompatActivity {
@Inject
HttpObject httpObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
((MyApplication)getApplication()).getAppComponent().injectSecondActivity(this);
Log.i("zhang_xin",httpObject.hashCode()+"");
}
}
打印輸出結(jié)果
2019-10-25 22:36:18.469 27216-27216/com.example.dagger2test I/zhang_xin: 134041457
2019-10-25 22:36:18.469 27216-27216/com.example.dagger2test I/zhang_xin: 134041457
2019-10-25 22:36:18.469 27216-27216/com.example.dagger2test I/zhang_xin: 125137238
2019-10-25 22:36:27.658 27216-27216/com.example.dagger2test I/zhang_xin: 134041457
第十一部份:增加表示層對象PresenterModule PresenterComponent
我們現(xiàn)在增加了PresenterModule和PresenterComponent跋破,我同樣希望把它注入到MainActivity中。
我們在創(chuàng)建PresenterComponent
package com.example.dagger2test;
import dagger.Component;
/**
* @author writing
* @time 2019/10/26 12:35
* @note
*/
@Component(modules = {PresenterModule.class})
public interface PresenterComponent {
void injectMainActivity(MainActivity mainActivity);
}
但這個(gè)時(shí)候我們只要Rebuild就會報(bào)錯(cuò)瓶蝴,原因也很簡單毒返,我們要注入MainActivity,就會生成MainActivity_MembersInjector類囊蓝,但現(xiàn)在我們有兩個(gè)Compent都要生成MainActivity_MembersInjector類饿悬,就會產(chǎn)生沖突。
我們看下完整代碼聚霜,是怎么解決的
先創(chuàng)建PresenterModule和PresenterObject
package com.example.dagger2test;
/**
* @author writing
* @time 2019/10/26 12:33
* @note
*/
public class PresenterObject {
}
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/26 12:34
* @note
*/
@Module
public class PresenterModule {
@Provides
public PresenterObject providePresenterObject(){
return new PresenterObject();
}
}
創(chuàng)建PresenterObjectComponent狡恬,不直接注入MainActivity中
package com.example.dagger2test;
import dagger.Component;
/**
* @author writing
* @time 2019/10/26 12:35
* @note
*/
@Component(modules = {PresenterModule.class})
public interface PresenterObjectComponent {
// void injectMainActivity(MainActivity mainActivity);
//這樣組件就不在注入到MainActivity中了,只負(fù)責(zé)對象提供
PresenterObject providerPresenterObject();
}
修改MyCmponent和MyApplication
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
/**
* @author writing
* @time 2019/10/25 21:33
* @note
*/
@Singleton
@Component(modules = {HttpModule.class,DatabaseModule.class},dependencies = {PresenterObjectComponent.class})
public interface MyComponent {
void injectMainActivity(MainActivity mainActivity);
void injectSecondActivity(SecondActivity secondActivity);
}
package com.example.dagger2test;
import android.app.Application;
/**
* @author writing
* @time 2019/10/25 21:51
* @note
*/
public class MyApplication extends Application {
private MyComponent myComponent;
@Override
public void onCreate() {
super.onCreate();
myComponent = DaggerMyComponent.builder().httpModule(new HttpModule())
//rebuild后增加presenterObjectComponent
.presenterObjectComponent(DaggerPresenterObjectComponent.create()).build();
}
public MyComponent getAppComponent(){
return myComponent;
}
}
看下MainActivity代碼
package com.example.dagger2test;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
HttpObject httpObject;
@Inject
HttpObject httpObject2;
@Inject
DatabaseObject databaseObject;
@Inject
PresenterObject presenterObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((MyApplication)getApplication()).getAppComponent().injectMainActivity(this);
Log.i("zhang_xin",httpObject.hashCode()+"");
Log.i("zhang_xin",httpObject2.hashCode()+"");
Log.i("zhang_xin",databaseObject.hashCode()+"");
Log.i("zhang_xin",presenterObject.hashCode()+"");
findViewById(R.id.textView).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
}
}
打印輸出如下
2019-10-26 13:01:10.736 6681-6681/com.example.dagger2test I/zhang_xin: 33405208
2019-10-26 13:01:10.736 6681-6681/com.example.dagger2test I/zhang_xin: 33405208
2019-10-26 13:01:10.736 6681-6681/com.example.dagger2test I/zhang_xin: 134041457
2019-10-26 13:01:10.736 6681-6681/com.example.dagger2test I/zhang_xin: 125137238
其余代碼同第十部分
第十二部份:兩個(gè)單例的寫法
我們現(xiàn)在在PresentModule和PresentComponent添加@Singlenton會rebuild錯(cuò)誤
我們看下Singleton這個(gè)注釋源碼
/*
* Copyright (C) 2009 The JSR-330 Expert Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.inject;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Identifies a type that the injector only instantiates once. Not inherited.
*
* @see javax.inject.Scope @Scope
*/
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
Scope(繪畫空間)是類似于作用域蝎宇,標(biāo)識只在某種地方(比如一個(gè)類弟劲,一個(gè)頁面,一個(gè)瀏覽器)有效.這個(gè)問題怎么解決呢姥芥?原因也很簡單兔乞,我們不使用@Single通這個(gè)坑貨,我們定義自己的@Singleton
創(chuàng)建自己的MySingleton
package com.example.dagger2test;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Scope;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @author writing
* @time 2019/10/26 13:16
* @note
*/
@Scope
@Documented
@Retention(RUNTIME)
public @interface MySingleton {
}
我們把第十部分凉唐,第十一部分中的@Singleton全部換成@MySingleton,運(yùn)行可以發(fā)現(xiàn)沒有任何問題
這里我就強(qiáng)調(diào)兩點(diǎn)
@Singleton只是一個(gè)模板庸追,我們需要scope都自定義
dependencies:組件依賴
- 1.多個(gè)組件之間的scope不能相同
- 2.沒有scope的不能依賴有scope的組件
package com.example.lsn37_dagger2.di;
import com.example.lsn37_dagger2.MainActivity;
import com.example.lsn37_dagger2.SecActivity;
import com.example.lsn37_dagger2.di.presenter_di.PresenterComponent;
import com.example.lsn37_dagger2.di.scope.AppScope;
import javax.inject.Singleton;
import dagger.Component;
import dagger.Subcomponent;
/**
* 這就是一個(gè)組件
* @Singleton只是一個(gè)模板,我們需要scope都自定義
* dependencies:組件依賴
* 1.多個(gè)組件之間的scope不能相同
* 2.沒有scope的不能依賴有scope的組件
*/
@AppScope
@Component(modules = {HttpModule.class,DatabaseModule.class}
,dependencies = {PresenterComponent.class})
public interface MyComponent {
void injectMainActivity(MainActivity mainActivity);
void injectSecActivity(SecActivity secActivity);
}
如果我們需要PresenterObject也單例該如何操作呢台囱?很好辦淡溯,在自定義一個(gè)單例
package com.example.dagger2test;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Scope;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @author writing
* @time 2019/10/26 13:16
* @note
*/
@Scope
@Documented
@Retention(RUNTIME)
public @interface MySingleton1 {
}
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/26 12:34
* @note
*/
@MySingleton1
@Module
public class PresenterModule {
@MySingleton1
@Provides
public PresenterObject providePresenterObject(){
return new PresenterObject();
}
}
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
/**
* @author writing
* @time 2019/10/26 12:35
* @note
*/
@MySingleton1
@Component(modules = {PresenterModule.class})
public interface PresenterObjectComponent {
// void injectMainActivity(MainActivity mainActivity);
//這樣組件就不在注入到MainActivity中了,只負(fù)責(zé)對象提供
PresenterObject providerPresenterObject();
}
其它的代碼不變簿训,可以發(fā)現(xiàn)presenterObject和HttpObject都是單例了
第十三部分咱娶,SubComponent的使用米间,組件與組件依賴的另一種方式
上面我們用組件依賴我們使用dependcies,現(xiàn)在我們換一種方式。
我們新創(chuàng)建一個(gè)項(xiàng)目
兩個(gè)Object膘侮,需要通過注入創(chuàng)建的對象
package com.example.dagger2test2;
/**
* @author writing
* @time 2019/10/26 14:21
* @note
*/
public class DataBaseObject {
}
package com.example.dagger2test2;
/**
* @author writing
* @time 2019/10/26 14:21
* @note
*/
public class HttpObject {
}
兩個(gè)module
package com.example.dagger2test2;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/26 14:26
* @note
*/
@Module
public class DataBaseModule {
@Provides
public DataBaseObject providersDataBaseObject(){
return new DataBaseObject();
}
}
package com.example.dagger2test2;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/26 14:25
* @note
*/
@Module
public class HttpObjectModule {
@Provides
public HttpObject providerHttpObject(){
return new HttpObject();
}
}
兩個(gè)Component
package com.example.dagger2test2;
import dagger.Subcomponent;
/**
* @author writing
* @time 2019/10/26 14:31
* @note 這就是一個(gè)子組件
*/
@Subcomponent(modules = {DataBaseModule.class})
public interface DatabaseObjectComponent {
void injectmMainActvity(MainActivity mainActivity);
}
package com.example.dagger2test2;
import dagger.Component;
/**
* @author writing
* @time 2019/10/26 14:29
* @note
*/
@Component(modules = {HttpObjectModule.class})
public interface HttpObjectComponent {
// void injectMainActivity(MainActivity mainActivity);
DatabaseObjectComponent databaseObjectComponent();
}
MainActivity中調(diào)用
package com.example.dagger2test2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
DataBaseObject dataBaseObject;
@Inject
HttpObject httpObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerHttpObjectComponent.builder().httpObjectModule(new HttpObjectModule())
.build()
//我們自己HttpObjectComponent中定義的方法
.databaseObjectComponent().injectmMainActvity(this);
Log.i("zhang_xin",dataBaseObject.hashCode()+"");
Log.i("zhang_xin",httpObject.hashCode()+"");
}
}
打贏輸出
2019-10-26 15:28:28.194 15101-15101/com.example.dagger2test2 I/zhang_xin: 134041457
2019-10-26 15:28:28.195 15101-15101/com.example.dagger2test2 I/zhang_xin: 125137238
第十四部分:集合傳參
修改HttpObject
package com.example.dagger2test2;
/**
* @author writing
* @time 2019/10/26 14:21
* @note
*/
public class HttpObject {
public String baseUrl;
public HttpObject(String baseUrl){
this.baseUrl = baseUrl;
}
public HttpObject(){}
}
修改HttpObjectModule
package com.example.dagger2test2;
import java.util.ArrayList;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
/**
* @author writing
* @time 2019/10/26 14:25
* @note
*/
@Module
public class HttpObjectModule {
//參數(shù)可能不是一個(gè)屈糊,我們定義一個(gè)集合裝參數(shù)
ArrayList<String> baseUrls;
public HttpObjectModule(ArrayList<String> baseUrls){
this.baseUrls = baseUrls;
}
@Named("baseurl1")
@Provides
public HttpObject providerHttpObject1(){
return new HttpObject(baseUrls.get(0));
}
@Named("baseurl2")
@Provides
public HttpObject providerHttpObject2(){
return new HttpObject(baseUrls.get(1));
}
}
其它的不變
我們看下MainActivity中的調(diào)用
package com.example.dagger2test2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
import javax.inject.Inject;
import javax.inject.Named;
public class MainActivity extends AppCompatActivity {
@Inject
DataBaseObject dataBaseObject;
@Named("baseurl1")
@Inject
HttpObject httpObject1;
@Named("baseurl2")
@Inject
HttpObject httpObject2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url1 = "www.baidu1.com";
String url2 = "www.baidu2.com";
ArrayList<String> urls = new ArrayList<>();
urls.add(url1);
urls.add(url2);
DaggerHttpObjectComponent.builder().httpObjectModule(new HttpObjectModule(urls))
.build()
//我們自己HttpObjectComponent中定義的方法
.databaseObjectComponent().injectmMainActvity(this);
Log.i("zhang_xin", dataBaseObject.hashCode() + "");
Log.i("zhang_xin", httpObject1.baseUrl + "");
Log.i("zhang_xin", httpObject2.baseUrl + "");
}
}
看下打印輸出的結(jié)果
2019-10-26 16:28:16.855 18917-18917/com.example.dagger2test2 I/zhang_xin: 33405208
2019-10-26 16:28:16.855 18917-18917/com.example.dagger2test2 I/zhang_xin: www.baidu1.com
2019-10-26 16:28:16.855 18917-18917/com.example.dagger2test2 I/zhang_xin: www.baidu2.com
第十五部分,解決Subcomponent傳參的問題
在第十三部分中琼了,我們有一個(gè)問題逻锐,那就是DataBaseObject這個(gè)類無法傳參,讀者可以自己試試雕薪,我這里就不演示了谦去。這是不是太坑了啊,我們在第十五部分就來解決這個(gè)問題蹦哼。解決辦法就是使用dependencies,這個(gè)在上面已經(jīng)有案例,就不講了要糊。