王學(xué)崗Dagger2的使用從簡單到復(fù)雜

第一部分

dagger2是一個(gè)依賴注入的框架,舉個(gè)例子如果我們不適用dagger注入,我們調(diào)用一個(gè)對(duì)象必須使用構(gòu)造方法,這樣就會(huì)造成了類與類的組合,但dagger的使用解決了這一問題。
這是dagger的官網(wǎng)

我們看一下跟dagger相關(guān)的概念,
@Inject
通常在需要依賴的地方使用這個(gè)注解。換句話說,你用它告訴Dagger這個(gè)類或者字段需要依賴注入。這樣,Dagger就會(huì)構(gòu)造一個(gè)這個(gè)類的實(shí)例并滿足他們的依賴。 官方點(diǎn)說就是帶有此注解的屬性或構(gòu)造方法將參與到依賴注入中,Dagger2會(huì)實(shí)例化有此注解的類。
@Module
Modules類里面的方法專門用來提供依賴,他就像一個(gè)工廠一樣去生產(chǎn)需要添加依賴的實(shí)例。所以我們定義一個(gè)類,用@Module來注解,這樣Dagger在構(gòu)造類的實(shí)例的時(shí)候,就知道從哪里去找到需要的依賴。modules的一個(gè)重要特性是它們?cè)O(shè)計(jì)為分區(qū)并組合在一起(例如,我們的app中可以有多個(gè)組成在一起的modules)。它里面定義一些用@Provides注解的以provide開頭的方法,這些方法就是所提供的依賴,Dagger2會(huì)在該類中尋找實(shí)例化某個(gè)類所需要的依賴。
@Provides
上面引入了這個(gè)概念了。在modules中,我們定義的方法是用@Provides這個(gè)注解,以此來告訴Dagger我們想要構(gòu)造對(duì)象并提供這些依賴。
@Component
Components從根本上來說他就是一個(gè)注入器,也可以說是用來將@Inject和@Module聯(lián)系起來的橋梁,它的主要作用就是連接這兩個(gè)部分。Components可以提供所有定義了的類型的實(shí)例(inject需要),比如:我們必須用@Component注解一個(gè)接口然后列出所有的 。功能是從@Module中獲取依賴并將依賴注入給@Inject

dagger必不可少的三個(gè)元素:Module,Component,Container
這里有張圖來說明它們之間的關(guān)系。


dagger2222222222.png

第二部分 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就會(huì)從@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í)例,我們?cè)贏piService上加上@inject注解,這樣dagger就知道我們需要ApiService的實(shí)例,dagger就會(huì)去@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í)例。
我們?cè)诳聪耈seModele類,在這個(gè)類里獲取ApiService的實(shí)例,注意,該類需要添加@module注解。提供對(duì)象的方法添加@Prividers,方法的返回值為ApiService且有@Provides注釋,那么dagger就會(huì)從這個(gè)方法里獲取ApiService對(duì)象

package com.example.dagger2test;

import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
    @Provides//提供依賴
    public ApiService provideApiService(){
        return new ApiService();
    }
}

到這里我們?cè)贛ainActivity(Container)里調(diào)用ApiService實(shí)例的代碼就全部完成了。然后我們r(jià)ebuild我們的工程
這個(gè)時(shí)候dagger會(huì)自動(dòng)生成DaggerUserComponet類,該類有個(gè)create(),會(huì)生成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會(huì)從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)行會(huì)輸出
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會(huì)從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的基本使用(下)

我們?cè)賮砜匆幌聫?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注冊(cè)成功");
    }
}

我們有兩種方法
第一種,修改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注冊(cè)成功
第二種方法,使用構(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注冊(cè)成功");
    }
}

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注冊(cè)成功
由以上兩種方法我們可以得出結(jié)論。
如果Module中沒有提供@Providers注釋的方法,Dagger會(huì)去調(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)在大家看下,我們?cè)趺丛贛ainActivity類里調(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是單例對(duì)象
    public ApiService(Dog dog) {
        this.dog = dog;
    }

    public void register() {
        Log.i("zhang_xin", "ApiService register成功");
    }
}

我們可以單獨(dú)寫一個(gè)針對(duì)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
}

下面我們?cè)贛ainActivity中調(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注冊(cè)成功
多次打印都是這個(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)在有新的需求了,我們?cè)贛ainActivity里需要兩個(gè)ApiService對(duì)象,該怎么操作呢?其實(shí)也很簡單,只需要在UseModule中提供兩個(gè)@Provides注釋的方法,同時(shí)在MainActivity和UseModule中添加@Named注釋,注意MainActivity中的@Named和UseModule中的@Named字段要一一對(duì)應(yīng)??聪麓a更一目了然
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è)對(duì)象前添加@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一一對(duì)應(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è)不同的對(duì)象。
注意,如果我們不添加@Named注釋,dagger會(huì)根據(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)行都會(huì)打印這個(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è)對(duì)象。

第八部分:Singleton 單例講解(下)

我們第七部分實(shí)現(xiàn)了單例模式,但是這種方法實(shí)現(xiàn)的單例模式是有問題的,如果我們現(xiàn)在在創(chuàng)建一個(gè)MainActivity2和與之相關(guān)的@Component注釋的類,那么這個(gè)時(shí)候我們無法保證兩個(gè)Activity中的ApiService是同一個(gè)。其實(shí)大家翻翻Dagger的源碼就會(huì)發(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注冊(cè)成功");
    }
}

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注冊(cè)成功 /zhang_xin: com.example.daggertest2.CallNets@eea8d0f /zhang_xin: apiService注冊(cè)成功
很明顯,兩個(gè)CallNets不是同一個(gè)對(duì)象,我們雖然標(biāo)注了@Singleton,但因?yàn)閯?chuàng)建了兩個(gè)Componet,所以得到的是兩個(gè)不同的CallNets對(duì)象。
接下來我們就解決這個(gè)問題。
我們需要?jiǎng)?chuàng)建一個(gè)最高級(jí)別的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)槲覀儾恍枰⑷?,是依附于其它的Conmponent
}

我們?cè)贏ppModule類中提供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í)例
 * 他就會(huì)去依賴既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);
}

這里我做下說明


dagger1.ng.png

注意第五點(diǎn),所以我們沒辦法給LoginComponent和AppComponent添加@Singleton注釋,既然沒辦法添加@Singleton注釋,那么我們?cè)撛趺唇oLoginComponent和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 級(jí)別,有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í)例
 * 他就會(huì)去依賴既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對(duì)象就是由AppModule提供的。
我們現(xiàn)在reBuild工程,已經(jīng)可以了沒有報(bào)錯(cuò)
可是我們現(xiàn)在又面臨一個(gè)問題,接下來我們?cè)撛鯓釉贚oginActivity和MainActivity中使用AppComponent呢?
DaggerUserComponet.builder().userModule(new UserModule()).appComponet();
我們可以看到appComponent()需要傳入AppComponet類型的對(duì)象,在這里我們?cè)趺唇oappComponent()傳入?yún)?shù)呢?
因?yàn)镾ingleton是application級(jí)別的,所以我們需要在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)了單例模式
我們?cè)贏piService中添加打印數(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注冊(cè)成功"+this.callNets.toString());
    }
}

看下打印結(jié)果

10-24 16:22:59.691 2967-2967/com.example.daggertest2 I/zhang_xin: apiService注冊(cè)成功com.example.daggertest2.CallNets@4a7ac880
10-24 16:22:59.701 2967-2967/com.example.daggertest2 I/zhang_xin: apiService注冊(cè)成功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è)通過注入獲取對(duì)象的類

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 {
}

對(duì)應(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

第十一部份:增加表示層對(duì)象PresenterModule PresenterComponent

我們現(xiàn)在增加了PresenterModule和PresenterComponent,我同樣希望把它注入到MainActivity中。
我們?cè)趧?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就會(huì)報(bào)錯(cuò),原因也很簡單,我們要注入MainActivity,就會(huì)生成MainActivity_MembersInjector類,但現(xiàn)在我們有兩個(gè)Compent都要生成MainActivity_MembersInjector類,就會(huì)產(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é)對(duì)象提供
     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會(huì)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)識(shí)只在某種地方(比如一個(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é)對(duì)象提供
     PresenterObject providerPresenterObject();
}

其它的代碼不變,可以發(fā)現(xiàn)presenterObject和HttpObject都是單例了

第十三部分,SubComponent的使用,組件與組件依賴的另一種方式

上面我們用組件依賴我們使用dependcies,現(xiàn)在我們換一種方式。
我們新創(chuàng)建一個(gè)項(xiàng)目
兩個(gè)Object,需要通過注入創(chuàng)建的對(duì)象

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è)類無法傳參,讀者可以自己試試,我這里就不演示了。這是不是太坑了啊,我們?cè)诘谑宀糠志蛠斫鉀Q這個(gè)問題。解決辦法就是使用dependencies,這個(gè)在上面已經(jīng)有案例,就不講了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容