• The ultimate goal of this blog series is to build the MVP + Dagger2 framework
  • This blog series contains the following posts:
  1. Dagger series 1 — Prelude: Basic introduction to dependency injection
  2. Dagger 2 series (2) — Basic: @Inject, @Component
  3. Dagger: @Module & @Provides
  4. Dagger 2 series (4) — Foundation: @named & @Qualifier
  5. Dagger: @Scope & @singleton

What you will see in this article:

  • @NamedWhat is the
  • @QualifierWhat is the
  • @Named@QualifierWhat problem was it used to solve

If you need to have multiple implementations of the same class in the same Module with the @provides flag, you can expect a similar error message at compile time:

Error: XXXX.UserThird is bound multiple times: @Provides xxxUserThird xxxxx.UserThirdModule.provideUserThird() @Provides xxx.UserThird xxx.UserThirdModule.provideUserThirdWithoutParams()

The general information is that the UserThird class is bound multiple times and lists the binding information. The reason for the error is that we provide a method to create an instance of the class that returns the same value, but the program is not smart enough to figure out which method to use to create the instance, so the compiler throws an exception, a phenomenon known as dependency injection disorientation.

But such operations are normal in normal business, it is unavoidable not to use. @named and @Qualifier can be used to solve this problem.

@Named

Its specific use method is as follows:

  1. use@NamedTags methods in Module that generate class instances
  2. use@NamedMarks the corresponding class instance in the target class

Both steps are indispensable. Let’s look at the code:

  • POJO class
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 and getter methods for variables..... }Copy the code
  • The Module class

@Module
public class UserThirdModule {

    @Named("a")
    @Provides
    UserThird provideUserThird() {return new UserThird("Male", 1243); } @Named("b")
    @Provides
    UserThird provideUserThirdWithoutParams() {
        returnnew UserThird(); }}Copy the code
  • The target class
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("Female");
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoC.getSex() + "Number." + mUserTwoC.getCarNum());
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoD.getSex() + "Number."+ mUserTwoD.getCarNum()); }}Copy the code

Note that the @named annotation method is used in the Module class and the @named annotation in the target class to mark instance variables of the class, and that there is a one-to-one correspondence between @named (” A “) in the Module and @named (” A “) in the target class.

@Qualifier

The @qualifier function implemented by @named can also be implemented, but we need to customize annotations to complete it. Specific application scenarios are as follows:

  • Custom annotations
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface UserThirdQualifier {
    String value() default "";
}
Copy the code

Note that custom annotations need to be annotated with @qualifier.

  • Tag in the Module class
@Module
public class UserThirdModule {

    @UserThirdQualifier("c")
    @Provides
    UserThird provideUserThird() {return new UserThird("Male", 1243); } @UserThirdQualifier("d")   
    @Provides
    UserThird provideUserThirdWithoutParams() {
        returnnew UserThird(); }}Copy the code
  • The target class
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("Female");
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoC.getSex() + "Number." + mUserTwoC.getCarNum());
        Log.e(TAG, "onCreate: " + "sex" + mUserTwoD.getSex() + "Number."+ mUserTwoD.getCarNum()); }}Copy the code

Again, the code needs to focus on the @UserThirdQualifier annotation method in the Module class and the @UserThirdQualifier annotation in the target class to mark instance variables of the class. And the @UserThirdQualifier(” C “) in the Module matches the @UserThirdQualifier(” C “) in the target class.

conclusion

The @named and @qualifier annotations can be used to identify dependency injection disorientation caused by providing the same class instance object in the same Module.