###自定义Scope
我们知道component的dependencies与component自身的scope不能相同,即组件之间的scope不同
意思就是当我们写了一个componentA,同时通过dependencies引用了另一个componentB
如下面代码所示
@Component(modules = AModule.class,dependencies = ComponentB.class)
public interface ComponentA {
...
}
在我们componentB中,使用了**@Singleton** (单例)Scope,
/**
* description:
* author: dujun
* created at: 2018/1/23 16:37
* update: 2018/1/23
* version: 1.0
*/
@Singleton
@Component(modules = {BModule.class})
public interface BComponent {
...
}
所以,因为componentA通过dependencies引用了componentB,所以中componentA也要使用一个同样的Scope,回到开始的那句话:
component的dependencies与component自身的scope不能相同,即组件之间的scope不同
此时,我们就需要自定义一个Scope
首先,创建一个接口在interface前加@
public @interface CustomScope {
}
我们照猫画虎,打开Singleton的源码:
/**
* Identifies a type that the injector only instantiates once. Not inherited.
*
* @see javax.inject.Scope @Scope
*/
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
则,我们的自定义CustomScope完整代码为:
/**
* description:
* author: dujun
* created at: 2018/1/23 17:48
* update: 2018/1/23
* version: 1.0
*/
@Scope
@Documented
@Retention(RUNTIME)
public @interface CustomScope{
}
我们看看上面@Scope、@Documented、@Retention(RUNTIME)分别代表什么
**@Scope :**注明是Scope
**@Documented :**标记在文档
**@Retention(RUNTIME) :**运行时级别
此时,componentA的代码为:
@CustomScope
@Component(modules = AModule.class,dependencies = ComponentB.class)
public interface ComponentA {
...
}
###SubComponent的使用
通常,component之间的相互引用,用dependencies,我们还可以通过SubComponent来完成
下面定义了父component和module
/**
* description:父Component
* author: dujun
* created at: 2018/1/24 15:47
* update: 2018/1/24
* version: 1.0
*/
@Singleton
@Component(modules = FMudule.class)
public interface FComponent {
}
/**
* description:父Mudule
* author: dujun
* created at: 2018/1/24 15:55
* update: 2018/1/24
* version: 1.0
*/
@Module
public class FMudule {
@Singleton
@Provides
public Gson provideGson(){
return new Gson();
}
}
首先,我们看到上面FMudule使用了 @Singleton,所以,这里需要说一个注意问题:
SubComponent的Scope范围小于父Component
所以,子类中如果要使用Scope,则需要自定义。假设Subcomponent 中,也需要使用 @Singleton。由于父Component使用了**@Singleton**,所以这里需要自定义,所以使用了我们自定义的**@CustomScope**
子Component类代码如下:
/**
* description:子Component
* author: dujun
* created at: 2018/1/24 15:49
* update: 2018/1/24
* version: 1.0
*/
@CustomScope
@Subcomponent(modules = ZModule.class)
public interface ZComponent {
...
}
/**
* description:子Module
* author: dujun
* created at: 2018/1/24 15:54
* update: 2018/1/24
* version: 1.0
*/
@Module
public class ZModule {
@CustomScope
@Provides
public User provideUser(){
return new User();
}
}
那么FComponent与ZComponent怎么关联呢 ?,我们只需要在FComponent接口中添加如下抽象方法:
/**
* description:父Component
* author: dujun
* created at: 2018/1/24 15:47
* update: 2018/1/24
* version: 1.0
*/
@Singleton
@Component(modules = FMudule.class)
public interface FComponent {
// 关联@Subcomponent
ZComponent getChildComponent();
}
最后,还有一点注意的是:
**Subcomponent同时具备两种不同生命周期的scope, SubComponent具备了父Component拥有的Scope,也具备了自己的Scope。 **
假设我们需要注入User对象,我们会根据使用情况不同,又是会用到Lazy元素和Provider元素
下面是一个实例:
public class Container{
@Inject
Lazy lazyUser; //注入Lazy元素
@Inject
Provider providerUser; //注入Provider元素
public void init(){
DaggerComponent.create().inject(this);
//在这时才创建user1,以后每次调用get会得到同一个user1对象
User user1=lazyUser.get();
//在这时创建user2,以后每次调用get会再强制调用Module的Provider方法一次,根据Provides方法具体实现的不同,可能返回跟user2是同一个对象,也可能不是。
User user2=providerUser.get();
}
}
通过上面的实例,我们可以知道俩个元素分别代表的含义:
**Lazy : **调用其get()方法的时候才会创建注入对象的实例,也就是我们通常所说的懒加载。
**Provider: **同样,也是调用其get方法的时候才会创建注入对象的实例,但是,内地调用get方法,都用会先调用其Module的Provides方法一次,所以获取到的实例对象跟Provides方法内部具体实现有关。