Dagger2 使用方法

作者: 雨林雨林 | 来源:发表于2016-11-15 22:35 被阅读726次

    Dagger 2

    依赖注入框架

    资料

    Github

    官网

    API

    文档翻译

    导入

    • 配置模组的 build.gradle
    dependencies {
      dependencies {
        compile 'com.google.dagger:dagger:2.7'
        annotationProcessor 'com.google.dagger:dagger-compiler:2.7'
      }
    }
    

    基本用法

    构造

    @Inject

    • 可以注入成员变量、构造方法、成员方法
    // 在 Bean 的构造方法上添加注解 @Inject,只能注解一个构造方法,编译后生成 Xxx_Factory
    @Inject
    public Dog() {}
    
    // 创建接口 @Component,作为注入器,可以是接口或者抽象类,编译时产生类 DaggerXxxComponent
    @Component
    public interface DogComponent {
        // 注入方法,方法名任意,不能使用子类,编译后生成 Xxx_MembersInjector
        void inject(MainActivity activity);
    }
    
    // 在需要注入的成员变量上添加注解 @Inject,不能私有
    @Inject
    Dog dog;
    
    // 在编译生成代码后,注入
    DaggerDogComponent.create().inject(this);
    

    模组

    @Module@Provides

    • @Inject@Provides组成对象表,需注入对象时在表中查询
    • @Module的优先级高于@Inject,优先通过@Module生成实例
    // 在 Module 类上添加注解 @Module,编译后生成 XxxModule_ProvideXxxFactory
    @Module
    public class CatModule {
    
        @Provides  // 在生成方法上添加注解 @Provides
        Cat provideCat(String name) {
            return new Cat(name);
        }
    
        @Provides
        String provideString() {
            return "cat";
        }
    }
    
    // 在 Component 接口上添加注解 @Component,参数(modules)指向Module
    @Component(modules = CatModule.class)
    public interface CatComponent {
        void inject(MainActivity activity);
    }
    
    @Inject
    Cat cat;
    
    DaggerCatComponent.create().inject(this);
    

    注入器

    @Component

    • 如果你的@Component不是顶层的类型,那生成的component的名字将会包含它的封闭类型的名字,通过下划线连接。
    @Module
    public class SheepModule {
        @Provides
        Sheep provideSheep(String name) {
            return new Sheep(name);
        }
    }
    
    @Module
    public class NameModule {
        private String name;
    
        public NameModule(String name) {  // 参数可以通过 Module 的构造方法传入
            this.name = name;
        }
    
        @Provides
        String provideString() {
            return name;
        }
    }
    
    // 在 Component 接口上添加注解 @Component,参数(modules)指向多个 Module
    @Component(modules = {SheepModule.class, NameModule.class})
    public interface SheepComponent {
        void inject(MainActivity activity);
    
        // 公开可见的对象图表,编译后会生成对应的方法
        Sheep newSheep();
    }
    
    @Inject
    Sheep sheep;
    
    // 在生成代码后,构建注入器添加 Module 和参数
    SheepComponent component = DaggerSheepComponent.builder().nameModule(new NameModule("sheep")).build();
    component.inject(this); // 注入,注入标注 @Inject 的对象
    Sheep sheep = component.newSheep(); // 调用方法,获取对象
    

    作用域

    @Scope@Singleton@Reusable(测试)

    • @Scope 作用域,在作用域内保持单例,单例对象保存于Component中
    • @Singleton 单例,为@Scope的实现注解
    • @Reusable 重用,首次使用缓存起来重复使用
    • 可添加在@Provides标注的方法上或实例类上
    • Components可以有多种域注解,表明这些注解是同一个域的别名
    // 自定义注解@DefaultScope
    @Scope
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DefaultScope {
    }
    
    @Module
    public class HorseModule {
      @Provides @DefaultScope  // 添加注解 @DefaultScope
      Horse provideHorse() {
          return new Horse();
      }
    }
    
    @DefaultScope  // 添加注解 @DefaultScope
    @Component(modules = HorseModule.class)
    public interface HorseComponent {
        void inject(MainActivity activity);
    
        Horse newHorse();
    }
    
    @Inject
    Horse horse;
    
    // 注入的对象和获取的对象为同一对象,单例
    HorseComponent component = DaggerHorseComponent.builder().build();
    component.inject(this);
    Horse horse = component.newHorse();
    

    限定符

    @Qualifier@Named

    • @Qualifier 限定符
    • @Named 命名,为@Qualifier的实现注解
    // 自定义限定符 @RedPig 和 @BlackPig
    @Qualifier
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    public @interface RedPig {
    }
    
    @Qualifier
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    public @interface BlackPig {
    }
    
    @Module
    public class PigModule {
        @RedPig  // 添加限定符
        @Provides
        Pig provideRedPig() {
            return new Pig("Red Pig");
        }
    
        @BlackPig  // 添加限定符
        @Provides
        Pig provideBlackPig() {
            return new Pig("Black Pig");
        }
    }
    
    @Component(modules = PigModule.class)
    public interface PigComponent {
        void inject(MainActivity activity);
    
        @RedPig  // 公开的对象表,添加限定符
        Pig newRedPig();
    
        @BlackPig  // 公开的对象表,添加限定符
        Pig newBlackPig();
    }
    
    @RedPig  // 添加限定符
    @Inject
    Pig redPig;
    
    @BlackPig  // 添加限定符
    @Inject
    Pig blackPig;
    
    DaggerPigComponent.create().inject(this);
    

    加载

    Lazy<T>Provider<T>

    • Lazy<T> 延迟加载,首次使用才注入
    • Provider<T> 重新加载,每次重新注入
    • Lazy<T>不等于单例
    @Inject
    Lazy<Duck> duckLazy;
    
    @Inject
    Provider<Duck> duckProvider;
    
    T get()  // 获取对象
    

    进阶用法

    依赖

    @Component(dependencies)

    • 相互独立的 Component,被依赖的 Component 公开对象表
    @DefaultScope
    @Component(modules = HorseModule.class)
    public interface HorseComponent {
        void inject(ADActivity activity);
        // 依赖必须有公开的对象表
        Horse newHorse();
    }
    
    @MareScope // 作用域,和 HorseComponent 的不同
    @Component(modules = MareModule.class, dependencies = HorseComponent.class)
    public interface MareComponent {
        Mare newMare(); // MareModule 提供的对象表
    
        Horse newHorse(); // HorseComponent 提供的对象表
    }
    
    MareComponent component = DaggerMareComponent.builder().horseComponent(DaggerHorseComponent.create()).build();
    Mare mare = component.newMare();
    Horse horse = component.newHorse();
    

    继承

    @Subcomponent@Subcomponent.Builder

    • Component 结成一个整体,父 Component 不须公开对象列表,子 Component 自动获取所有的对象表
    • 子 Component 具备了父 Component 拥有的 Scope,也具备了自己的 Scope。不同作用域的对象存在各自的 Component 中
    // 父 Component,无须公开对象表,子自动获取
    @Singleton
    @Component(modules = DonkeyModule.class)
    public interface DonkeyComponent {
        // 声明子 Component 的获取方法,返回类型是 Subcomponent 类,方法名随意,参数是这个 Subcomponent 需要的 Modules,如 Modules 不用传参,可省略
        MuleComponent muleComponent(MuleModule module);
    }
    
    @MuleScope  // 子 Component 的 Scope 范围小于父 Component
    @Subcomponent(modules = MuleModule.class)
    public interface MuleComponent {
        // 父 Component 不能注入容器,子 Component 一起注入
        void inject(AHActivity activity);
    }
    
    @Inject
    Donkey donkey;
    
    @Inject
    Mule mule;
    
    DonkeyComponent donkeyComponent = DaggerDonkeyComponent.create();
    MuleComponent muleComponent = donkeyComponent.muleComponent(new MuleModule()); // 通过父获取子
    muleComponent.inject(this); // 子完成所有注入
    

    多重绑定

    @IntoSet@ElementsIntoSet@IntoMap(测试)

    @Module
    public class OneModule {
        @IntoSet  // 向 Set 返回一个元素
        @Provides
        static Pig provideOne(@RedPig Pig pig) {
            return pig;
        }
    }
    
    @Module
    public class TwoModule {
        @ElementsIntoSet  // 向 Set 返回多个元素
        @Provides
        static Set<Pig> provideTwo(@BlackPig Pig pig1, @BlackPig Pig pig2) {
            return new HashSet<Pig>(Arrays.asList(pig1, pig2));
        }
    
        @ElementsIntoSet
        @Provides
        static Set<Pig> primeEmpty() {
            return Collections.emptySet();  // 向 Set 返回空元素
        }
    }
    
    @Component(modules = {PigModule.class, OneModule.class, TwoModule.class})
    public interface SetComponent {
        Set<Pig> get(); // 显露的对象表
    }
    
    Set<Pig> pigs = DaggerSetComponent.create().get(); //获取到一个 Set<T>
    

    相关文章

      网友评论

        本文标题:Dagger2 使用方法

        本文链接:https://www.haomeiwen.com/subject/mrmlpttx.html