Dagger2 Dependencies与SubComponent 深入

依赖引用关系说明

参考链接

位于上层的component是看不到下层的,而下层则可以使用上层的,但不能引用同一层相邻component内的实例。

依赖图例子

Dagger2 Dependencies与SubComponent 深入_第1张图片

@Subcomponent 子组件绑定 绑定子组件中的对象除了可以依赖自身模块中绑定的对象外,

  • 还可以依赖于其父组件或任何祖先组件中绑定的任何对象。
  • 另一方面,绑定在父组件中的对象不能依赖于绑定在子组件中的对象。 绑定在一个子组件中的对象也不能依赖于同级子组件中绑定的对象。
  • –> 表示依赖 !–> 表示不依赖
  • 子绑定对象–>父绑定对象–>祖绑定对象(子可以依赖祖父) 父绑定对象 !–>子绑定对象 子绑定对象!–>同子绑定对象

Dependencies 依赖的使用

@Component为其依赖de @Component提供对象

public class Teacher {
    public String name;
    public int age;
    
}


@Module
public class TeacherMoudle {
    @Provides
    public Teacher provideFather(){
        return new Teacher();
    }
}

@Component(modules = TeacherMoudle.class)
public interface TeacherComponent {
  Teacher getTeacher();//写抽象方法暴露依赖 Teacher
}

public class Student {
    public String name;
    public int age;

    public Student(Teacher teacher) {

    }
}


@Module
public class StudentMoudle {

    @Provides
    public Student provideChild(Teacher teacher){
        return new Student(teacher);
    }
}
//dependencies 表示 StudentComponent 依赖于 TeacherComponent
@Component(modules = StudentMoudle.class,dependencies =TeacherComponent.class)
public interface StudentComponent {
     void inject(ComponentActivity activity);
  
}

public class ComponentActivity extends AppCompatActivity {
    private final static String TAG="LHW";
    @Inject
    Student student;
    @Inject
    Teacher teacher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_component);

       
    TeacherComponent teacherComponent = DaggerTeacherComponent.create();
    DaggerStudentComponent.builder().teacherComponent(teacherComponent).build().inject(this);
       
        student.name="拐骗";
        student.age=18;
        teacher.name="You Father";
        teacher.age=68;

        Log.d("LHW","ComponentActivity 注入成功 child="+ student);
        Log.d("LHW","ComponentActivity 注入成功 father="+ teacher);
    }
}

注意:

  1. 注入的时候,必须先实例TeacherComponent,再当做参数实例StudentComponent进行注入,如果@Module是有参构造方法的,按照正常调用在build()方法调用前实例化即可
  2. TeacherComponent 依然是可以独立作为一个容器注入依赖
  3. 有@Scope的@Component可以依赖无@Scope的@Component,有@Scope的@Component只能依赖有@Scope的@Component,并且两者的@Scope不能相同
  4. @Singleton的@Component只能被依赖而不能依赖任何@Component

SubComponent 使用

子Component,可以理解为继承或者拓展的意思

@Module(subcomponents = StudentComponent.class)
public class TeacherMoudle {
    @Provides
    public Teacher provideFather(){
        return new Teacher();
    }
}


@Component(modules = TeacherMoudle.class)
public interface TeacherComponent {
    StudentComponent.Builder buildStudentComponent();
}

@Module
public class StudentMoudle {

    @Provides
    public Student provideChild(Teacher teacher){
        return new Student(teacher);
    }
}

@Subcomponent(modules = StudentMoudle.class)
public interface StudentComponent {
     void inject(ComponentActivity activity);
     @Subcomponent.Builder
     interface Builder{
          StudentComponent build();
     }
}

    @Inject
    Student student;
    @Inject
    Teacher teacher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_component);

        TeacherComponent teacherComponent = DaggerTeacherComponent.create();
        teacherComponent.buildStudentComponent().build().inject(this);
     
        student.name="哈哈哈";
        student.age=18;
        teacher.name="YouTeacher";
        teacher.age=68;

        Log.d("LHW","ComponentActivity 注入成功 child="+ student);
        Log.d("LHW","ComponentActivity 注入成功 father="+ teacher);
    }
}

说明

1.TeacherMoudle 注入子 @Moudle(subcomponents=StudentComponent.class)

2.TeahcerComponent 构建一个获取StudentComponent子类的接口buildStudentComponent

  1. StudentComponent 添加注解@Subcomponent(modules = StudentMoudle.class)
    在StudentComponent类写一个内部接口Builder,必须要注解成@Subcomponent.Builder表示是顶级@Subcomponent的内部类

注意

  • (1)@Subcomponent不能再使用dependencies依赖其他@Component。
  • (2)@Subcomponent同样也可以被继承。
  • (3)@Subcomponent可以使用父@Component所有依赖,父@Component只有@Subcomponent.Builder实例,而不能使用@Subcomponent的依赖。
  • (4)@Scope的使用同样继承关系中也是不能相同,但没有子类不能使用@Singleton的限制。
  • (5)如果@Subcomponent指向的@Module是有参构造方法,写法如下,并且需要在build()方法调用前实例@Module:
    @Subcomponent.Builder
    interface Builder {
        ChildComponent build();
        Builder requestModule(ChildModule module);
    }

@Subcomponent 抽象工厂方法定义写法

@Subcomponent(modules = StudentModule.class)
public interface StudentComponent {
    void inject(ChildActivity activity);
}

@Component(modules = TeahcerModule.class)
public interface TeacherComponent {
    StudentComponent buildStudentComponent();
    //如果ChildModule是有参构造方法
    //StudentComponent buildStudentComponent(StudentModule studentModule);
}

官网提及比较重要的知识点:

  • (1)刚才所指的@Scope的使用在继承关系中不能相同,指的是父类与子类之间,如果父类有多个子类,子类与子类之间是可以相同,看Dagger2官网例子:
@Singleton 
@Component
interface RootComponent {
  SessionComponent.Builder sessionComponent();
}

@SessionScope 
@Subcomponent
interface SessionComponent {
  FooRequestComponent.Builder fooRequestComponent();
  BarRequestComponent.Builder barRequestComponent();
}

@RequestScope 
@Subcomponent
interface FooRequestComponent {...}

@RequestScope 
@Subcomponent
interface BarRequestComponent {...}

  • (2)使用Subcomponent的重要原因是封装应用的不同部分。父@Component负责维护共享的数据、对象,不同处则由各自的@Subcomponent维护,这跟Android封装Base公共类的思想类似。
  • (3)父子Component中的@Module,或Subcomponent的工厂方法定义的@Module,均不能定义重复的@Module,还是列出官方的例子:
@Component(modules = {RepeatedModule.class, ...})
interface ComponentOne {
  ComponentTwo componentTwo(RepeatedModule repeatedModule); // COMPILE ERROR!
  ComponentThree.Builder componentThreeBuilder();
}

@Subcomponent(modules = {RepeatedModule.class, ...})
interface ComponentTwo { ... }

@Subcomponent(modules = {RepeatedModule.class, ...})
interface ComponentThree {
  @Subcomponent.Builder
  interface Builder {
    Builder repeatedModule(RepeatedModule repeatedModule);
    ComponentThree build();
  }
}

DaggerComponentOne.create().componentThreeBuilder()
    .repeatedModule(new RepeatedModule()) // UnsupportedOperationException!
    .build();

你可能感兴趣的:(Android,框架&库学习集,android)