Dagger系列:
Demo地址:
在使用Dagger 2开发时,一般都是在Application中生成一个AppComponent,然后其他的功能模块的Component依赖于AppComponent,作为AppComponent的子组件。可是,对于将自组建添加到父组件有两种方式:
通过@Component的dependencies属性依赖父组件
@Component(modules = OrangeModule.class, dependencies = FruitComponent.class)
public interface OrangeComponent {
***
}
通过Moudle的subcomponents属性添加子组件
@Module(subcomponents = AppleSubcomponent.class)
public class FruitModule {
***
}
自己也是照葫芦画瓢采用了第一种方式,对于子组件(@Subcomponent)的认识也是一知半解,总是不能合理的封装,本篇文章深入了解@Subcomponent。
对于继承,大家应该都不陌生,其实就是子类继承父类,子类自动获取了的父类的属性和行为。我觉得我们也可以这么认为子组件。子组件是继承和扩展父组件的对象的组件。我们可以将应用程序的各个功能分割为模块,以将应用程序的不同部分彼此封装或在组件中使用多个范围。这不就是Android的模块化开发。
换句话说,相对于对象而言,自组件这么说 - 你的是我的,我的还是我的。父组件只能这么说 - 你的不是我的,我的是我的。
声明子组件,与普通组件声明类似,可以通过编写一个抽象类或接口来创建一个子组件,该类或接口声明了返回应用程序相关的类型的抽象方法。可以使用@Component,也可以使用@Subcomponent注解,这个没有一定的强制性。
与@Component注解不同的是,使用@Subcomponent注解子组件,必须声明其xxComponent.Builder,否则编译时,会报错。
@Subcomponent(modules = AppleModule.class)
public interface AppleSubcomponent {
AppleBean supplyApple();
@Subcomponent.Builder
interface Builder{
Builder appleModule(AppleModule module);
AppleSubcomponent build();
}
}
声明Module:OrangeModuleModule和FruitModule,其中OrangeModuleModule提供一个OrangeBean对象,而FruitModule提供一个Fruit对象
@Module
public class OrangeModule {
@Provides
public OrangeBean provideOrange() {
return new OrangeBean("这是一个橘子");
}
}
@Module
public class FruitModule {
@Provides
public Fruits provideFruit() {
return new Fruits("这是一个水果");
}
}
声明Component,并添加依赖关系
@Component(modules = OrangeModule.class, dependencies = FruitComponent.class)
public interface OrangeComponent {
void inject(OrangeFragment fragment);
}
@Component(modules = {FruitModule.class})
public interface FruitComponent {
***
// 将FruitModule中的Fruits暴露出来,以便于其他依赖于FruitComponent的Component调用
// 若不将Fruits暴露出来,依赖于FruitComponent的Component无法获取该实例,此时编译会报错,提示为该实例提供@Inject注解或者@Provides方法
Fruits supplyFruits();
}
注入依赖对象
public class OrangeFragment extends Fragment {
***
@Inject
OrangeBean mOrangeBean;
@Inject
Fruits mFruits;
public OrangeFragment() {
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
FruitComponent fruitComponent = DaggerFruitComponent.create();
OrangeComponent orangeComponent = DaggerOrangeComponent.builder()
.fruitComponent(fruitComponent)
.build();
orangeComponent.inject(this);
super.onCreate(savedInstanceState);
}
***
}
可以清晰的看出依赖关系,在示例中,OrangeComponent依赖于FruitComponent
注意:
依赖Component(OrangeComponent) 仅继承 被依赖Component(FruitComponent) 中显示提供的依赖。如果被依赖Component(FruitComponent)必须提供依赖注入的对象,也就是将对象实例暴露出来。否则,在子组件,也就是依赖Component(OrangeComponent)中,无法使用@Inject注入被依赖的Component(AppComponent)中的对象,此时编译器会报错,提示依赖注入的Xx实例没有提供@Inject注解或者@Provides方法。
声明AppleModule
@Module
public class AppleModule {
@Provides
public AppleBean privdeApple() {
return new AppleBean("这是一个苹果");
}
}
声明@SubComponent
@Subcomponent(modules = AppleModule.class)
public interface AppleSubcomponent {
//
AppleBean supplyApple();
@Subcomponent.Builder
interface Builder{
Builder appleModule(AppleModule module);
AppleSubcomponent build();
}
}
声明FruitModule,将AppleSubcomponent添加到subcomponents中
@Module(subcomponents = {AppleSubcomponent.class})
public class FruitModule {
@Provides
public Fruits provideFruit() {
return new Fruits("这是一个水果");
}
@Provides
@Type(value = "apple")
public Fruits provideSubApple(AppleSubcomponent.Builder builder) {
return new Fruits(builder
.appleModule(new AppleModule())
.build()
.supplyApple()
.toString());
}
}
声明FruitComponent,并将AppleSubcomponent.Builder暴露出来,以便依赖注入子组件的Builder
@Component(modules = {FruitModule.class})
public interface FruitComponent {
void inject(FruitActivity activity);
****
AppleSubcomponent.Builder supplyAppleSubcomponentBuilder();
}
依赖注入对象
public class FruitActivity extends AppCompatActivity {
***
// 依赖注入子组件的Builder
@Inject
Provider appleBulder;
AppleSubcomponent mAppleSubcomponent;
@Override
protected void onCreate(Bundle savedInstanceState) {
FruitComponent fruitComponent = DaggerFruitComponent.builder()
.build();
fruitComponent.inject(this);
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
***
mAppleSubcomponent = appleBulder.get().build();
AppleBean mAppleBean = mAppleSubcomponent.supplyApple();
}
***
}
关于SubComponent:
Dagger 2从浅到深(四)已经提到,在Dagger中,通过使用@Scope对组件进行注解,可以将组件与组件的生命周期相关联,实际上对注入器的控制。在这种情况下,组件实现保存对所有作用域对象的引用,从而可以重用它们。@Scope注解的@Provides方法的Module只能注入到到具有相同作用域的注解的组件中。
对于@Inject注解构造函数的类,也可以使用@Scope进行注解,这些“隐式绑定”可以被该作用域或任何其后代组件注释的任何组件使用,作用域实例将被绑定在被注解的作用域范围内。
正是这样,任何子组件与父组件不能使用相同的@Scope注解,因为子组件是在父组件中创建的,所以其生命周期应在父组件生命周期范围内,意味着子组件的生命周期与父组件的生命周期存在包含关系。比如:
@RootScope @Component
interface RootComponent {
BadChildComponent.Builder badChildComponent(); // ERROR!
SiblingComponentOne.Builder siblingComponentOne();
SiblingComponentTwo.Builder siblingComponentTwo();
}
@RootScope @Subcomponent
interface BadChildComponent {...}
@ChildScope @Subcomponent
interface SiblingComponentOne {...}
@ChildScope @Subcomponent
interface SiblingComponentTwo {...}
在示例中,BadChildComponent具有与父对象RootComponent相同的@RootScope注解,这是一个错误注解。但是SiblingComponentOne和SiblingComponentTwo都使用@ChildScope,因为两个子组件绑定同一个对象并不会产生混淆。
对于子组件而言,两个子组件使用相同的@Scope注解,这两个子组件内容的@Scope注解的实例是相对独立,互不关联。
@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 {...}
在示例中,RootComponent使用@Singleton注解。@SessionScope嵌套在@Singleton范围内,@RequestScope嵌套在@SessionScope中。值得注意的是,FooRequestComponent和BarRequestComponent尽管都用@RequestScope注解,但是它们都是SessionComponent的子组件,是相互独立的。
当相同的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()) // 运行时报错
.build();
好像有点懂了,从下图更能清楚地看清楚,两种添加子组件的区别: