Dagger 2 系列(四) -- 基礎篇:@Named 和 @Qualifier

Dagger2

  • 該系列博客的最終目標: 搭建 MVP + Dagger2 框架
  • 該系列博客包含如下幾篇內容:
  1. Dagger 2 系列(一) -- 前奏篇:依賴注入的基本介紹
  2. Dagger 2 系列(二) -- 基礎篇:@Inject、@Component
  3. Dagger 2 系列(三) -- 基礎篇:@Module 和@Provides
  4. Dagger 2 系列(四) -- 基礎篇:@Named 和 @Qualifier
  5. Dagger 2 系列(五) -- 進階篇:@Scope 和 @Singleton

在這篇文章中你會看到什麼:bash

  • @Named 是什麼
  • @Qualifier 是什麼
  • @Named@Qualifier 用瞭解決什麼問題

也許你會遇到這樣的需求: 在同一個 Module 中 經過 @Provides 標記多個提供相同類的不一樣實現對象,那麼你在編譯時能夠會遇到相似的報錯信息:框架

錯誤: xxxx.UserThird is bound multiple times: @Provides xxxUserThird xxxxx.UserThirdModule.provideUserThird() @Provides xxx.UserThird xxx.UserThirdModule.provideUserThirdWithoutParams()ide

其大體信息爲 UserThird 類被綁定了屢次,並列舉了綁定的信息。出錯的緣由是咱們提供了返回值相同的建立類實例的方法,可是程序沒有那麼智能,它是沒法判斷出應該使用哪個方法來建立實例,因此在編譯器就會拋出異常,這種現象稱爲 依賴注入迷失post

可是這樣的操做在正常的業務中是在正常不過的了,是沒法避免不去使用的。那麼此時 @Named@Qualifier 能夠用來解決此類問題。ui

@Named

其具體使用方法爲:this

  1. 使用 @Named 標記 Module 中生成類實例的方法
  2. 使用 @Named 標記目標類中相應類實例

兩步驟是缺一不可的。咱們來看一下具體代碼:spa

  • POJO 類
public class UserThird {

    private String mSex = "man";
    private int mCarNum = 7;
    
    public UserThird() {
    }
    public UserThird(String mSex, int mCarNum) {
        this.mSex = mSex;
        this.mCarNum = mCarNum;
    }
    // 變量的setter  和 getter 方法
    .....
}
複製代碼
  • Module 類
@Module
public class UserThirdModule {

    @Named("a")
    @Provides
    UserThird provideUserThird(){
        return new UserThird("男",1243);
    }
    
    @Named("b")
    @Provides
    UserThird provideUserThirdWithoutParams() {
        return new UserThird();
    }
}
複製代碼
  • 目標類
public class ThirdActivity extends AppCompatActivity {

    @Named("a")
    @Inject
    UserThird mUserTwoC;
    
    @Named("b")
    @Inject
    UserThird mUserTwoD;
    private static final String TAG = "SecondActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        DaggerUserThirdComponent.builder().userThirdModule(new UserThirdModule()).build().injectToThirdActivity(this);
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoC.getSex() + " number:" + mUserTwoC.getCarNum());
        mUserTwoC.setCarNum(46);
        mUserTwoC.setSex("女");
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoC.getSex() + " number:" + mUserTwoC.getCarNum());
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoD.getSex() + " number:" + mUserTwoD.getCarNum());
    }
}
複製代碼

以上代碼須要重點關注的是 Module 類 中使用 @Named 註解方法和在 目標類 中使用 @Named 註解標記類的實例變量,而且 Module 中的 @Named("a") 和 目標類中的 @Named("a") 是一一對應的。code

@Qualifier

以上經過 @Named 實現的標識功能 @Qualifier 一樣能夠實現,可是須要咱們自定義註解來完成,具體一個使用場景以下:cdn

  • 自定義註解
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface UserThirdQualifier {
    String value() default "";
}
複製代碼

注意,這裏自定義註解須要使用 @Qualifier 進行標註。對象

  • Module 類中標記
@Module
public class UserThirdModule {

    @UserThirdQualifier("c")
    @Provides
    UserThird provideUserThird(){
        return new UserThird("男",1243);
    }

    @UserThirdQualifier("d")   
    @Provides
    UserThird provideUserThirdWithoutParams() {
        return new UserThird();
    }
}

複製代碼
  • 目標類
public class ThirdActivity extends AppCompatActivity {
    @UserThirdQualifier("c")
    @Inject
    UserThird mUserTwoC;

    @UserThirdQualifier("d")
    @Inject
    UserThird mUserTwoD;

    private static final String TAG = "SecondActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        DaggerUserThirdComponent.builder().userThirdModule(new UserThirdModule()).build().injectToThirdActivity(this);
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoC.getSex() + " number:" + mUserTwoC.getCarNum());
        mUserTwoC.setCarNum(46);
        mUserTwoC.setSex("女");
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoC.getSex() + " number:" + mUserTwoC.getCarNum());
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoD.getSex() + " number:" + mUserTwoD.getCarNum());
    }
}
複製代碼

一樣的,以上代碼須要重點關注的是 Module 類 中使用 @UserThirdQualifier 註解方法和在 目標類 中使用 @UserThirdQualifier 註解標記類的實例變量,而且 Module 中的 @UserThirdQualifier("c") 和 目標類中的 @UserThirdQualifier("c")是一 一對應的。

總結

經過 @Named@Qualifier 兩個註解就能夠作到標識在同一個 Module 中提供相同類實例對象而形成的 依賴注入迷失 問題 。

相關文章
相關標籤/搜索