Dagger 2从浅到深(三)

Dagger系列:

  1. Dagger 2从浅到深(一)
  2. Dagger 2从浅到深(二)
  3. Dagger 2从浅到深(三)
  4. Dagger 2从浅到深(四)
  5. Dagger 2从浅到深(五)
  6. Dagger 2从浅到深(六)
  7. Dagger 2从浅到深(七)
  8. Dagger 2应用于Android的完美扩展库-dagger.android


Demo地址:

  1. DaggerLearn
  2. Kotlin-Dagger-2-Retrofit-Android-Architecture-Components

前面在Dagger 2从浅到深(二)中,提到@Provides方法返回的数据类型应该是唯一的。如果多个@Provides方法返回同一个数据类型,Dagger将不知道注入哪一个实例,从而造成了“依赖迷失”。此时,只要针对每种数据类型,写一个@Provides方法即可。可是,大家所熟悉的是,方法重载是Java的多态性的重要组成。如果对@Provides方法,重载多个,必然会造成“依赖迷失”。或者是,当一个类有多个构造被@Inject注解时,Dagger 2依然不知道使用哪个构造函数创建实例?

就像在冰箱里,有橘子、苹果、香蕉等水果,怎么才能准确的拿到我们想要的水果?我们大胆设想一下,如果对这些水果编号,重新定向水果。加入苹果的编号是2。当我们取编号2时,取到的水果就应该是苹果,而不是其他的水果。

在Dagger 2中,我们同样可以做,不管是构造函数还是@Provides方法,都进行编号处理。然后,在依据编号,调用相应的构造函数(或@Provides方法)创建实例,从而解决了“依赖迷失”问题。既然这样可以,那么久尝试这么干吧,看看结果如何!

@Qualifier

@Qualifier是javax.inject包下的注解,其是限定标识符。通过这个标识,可以对IOC容器中的实例进行编号,类似于Map中的Key。我们可以通过指定编号,从而获得我们想要的实例。

package javax.inject;

@Target(ANNOTATION_TYPE)
@Retention(RUNTIME)
@Documented
public @interface Qualifier {}

@Qualifier在Dagger中的应用

@Qualifier标识构造函数

  1. 自定义@Qualifier

    @Qualifier // 限定符
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Type {
        String value() default "";
    }
    
  2. 创建数据类AppleBean:在创建的AppleBean类中,有三个构造函数被@Inject注解,这样必然会造成了Dagger的“依赖迷失”。

    public class AppleBean {
        private String name;
        private double price;
        private String color;
    
        public AppleBean() {
        }
    
        public AppleBean(String color) {
            this.color = color;
        }
    
        public AppleBean(String name, double price) {
            this.name = name;
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "AppleBean{" +
                    "name='" + name + '\'' +
                    ", price=" + price +
                    '}';
        }
    }
    
  3. 修改Modle,使用限定符@Type来区分不同的构造函数new出来的对象

    @Module()
    public class FruitModule {
    
        //使用限定符来区别使用哪个构造函数返回对象
        @Type("color")
        @Provides
        public AppleBean provideColorApple() {
            return new AppleBean("red");
        }
    
        @Type("name")
        @Provides
        public AppleBean provideNameApple() {
            return new AppleBean("红富士", 6.88);
        }
    }
    
  4. 在目标类中,注入AppleBean实例

    public class FruitActivity extends AppCompatActivity {
    
        ***
        // 指定数据是哪个依赖提供方提供的
        @Type("color")
        @Inject
        AppleBean appleColorBean;
        @Type("name")
        @Inject
        AppleBean appleNameBean;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            FruitComponent fruitComponent = DaggerFruitComponent.builder()
                                                    .build();
            fruitComponent.inject(this);
            super.onCreate(savedInstanceState);
            setContentView(getLayoutId());
    
            ButterKnife.bind(this);
    
            initToolBar();
    
            //  appleColorBean:AppleBean{name='null', price=0.0, color='red'}
            Log.d("test", "appleColorBean:" + appleColorBean.toString());
            //  appleNameBean:AppleBean{name='红富士', price=6.88, color='null'}
            Log.d("test", "appleNameBean:" + appleNameBean.toString());
        }
    
        ***
    }
    

参考文档

  1. 浅析Dagger2的使用
  2. Android:dagger2让你爱不释手-基础依赖注入框架篇
  3. Android:dagger2让你爱不释手-重点概念讲解、融合篇
  4. Android:dagger2让你爱不释手-终结篇
  5. “一盘沙拉”带你入门Dagger2(一)之HelloWorld
  6. Dagger2图文完全教
  7. 为什么网上这么多dagger2教程,我还写了这篇文章。
  8. Android常用开源工具(1)-Dagger2入门

你可能感兴趣的:(Dagger)