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

在这篇文章中你会看到什么:

  • @Named 是什么
  • @Qualifier 是什么
  • @Named@Qualifier 用了解决什么问题

也许你会遇到这样的需求: 在同一个 Module 中 通过 @Provides 标记多个提供相同类的不同实现对象,那么你在编译时可以会遇到类似的报错信息:

错误: xxxx.UserThird is bound multiple times:
@Provides xxxUserThird xxxxx.UserThirdModule.provideUserThird()
@Provides xxx.UserThird xxx.UserThirdModule.provideUserThirdWithoutParams()

其大致信息为 UserThird 类被绑定了多次,并列举了绑定的信息。出错的原因是我们提供了返回值相同的创建类实例的方法,但是程序没有那么智能,它是无法判断出应该使用哪一个方法来创建实例,所以在编译器就会抛出异常,这种现象称为 依赖注入迷失

但是这样的操作在正常的业务中是在正常不过的了,是无法避免不去使用的。那么此时 @Named@Qualifier 可以用来解决此类问题。

@Named

其具体使用方法为:

  1. 使用 @Named 标记 Module 中生成类实例的方法
  2. 使用 @Named 标记目标类中相应类实例

两步骤是缺一不可的。我们来看一下具体代码:

  • 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") 是一一对应的。

@Qualifier

以上通过 @Named 实现的标识功能 @Qualifier 同样可以实现,但是需要我们自定义注解来完成,具体一个使用场景如下:

  • 自定义注解
@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 中提供相同类实例对象而造成的 依赖注入迷失 问题 。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Kotlin中,@Qualifier注解通常用于与依赖注入框架一起使用,以标识特定的依赖项。在使用依赖注入框架时,您可以使用@Qualifier注解来指定要注入的依赖项的特定实现。 以下是一个简单的示例,演示如何使用@Qualifier注解: ```kotlin interface MyDependency class MyFirstDependency : MyDependency { override fun toString(): String { return "MyFirstDependency" } } class MySecondDependency : MyDependency { override fun toString(): String { return "MySecondDependency" } } class MyComponent { @Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class FirstDependency @Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class SecondDependency @Inject @FirstDependency lateinit var firstDependency: MyDependency @Inject @SecondDependency lateinit var secondDependency: MyDependency } fun main(args: Array<String>) { val component = DaggerMyComponent.builder().build() println(component.firstDependency) // prints "MyFirstDependency" println(component.secondDependency) // prints "MySecondDependency" } ``` 在上面的示例中,我们定义了一个MyDependency接口,然后实现了两个具体的实现MyFirstDependency和MySecondDependency。接下来,我们定义了一个MyComponent类,其中包含了@FirstDependency和@SecondDependency注解来标识要注入的特定依赖项。最后,我们使用Dagger2库生成MyComponent实例,并打印出注入的依赖项。 请注意,@Qualifier注解本身并不提供任何特定的注入功能,而只是用于标识特定的依赖项。实际的注入功能由依赖注入框架提供。在上面的示例中,我们使用了Dagger2库来实现依赖注入。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值