一、关于@Scope
@Scope作用域其实是用来保持在实例有效作用域内的单例(由同一个Component提供)。比如系统自带的@Singleton,通常用在ApplicationComponent这个用来管理app全局实例的组件中,通过保持ApplicationComponent的单例才实现在整个应用生命周期内使用了@Singleton注解的依赖实例的单例,将其替换为其他自定义的作用域注解也可以有同样的作用。
1.Scope机制可以使得在scope存在时保持类的单例
2.没有指定作用域的@Provides方法会在每次注入的时候都创建新的对象
3.一个没有scope的组件component不可以依赖一个有scope的组件component,子组件和父组件的scope不能相同。
二、关于@SubComponent
@SubComponent注解的可以成为子组件或公共组件,是组织component的三种方式中包含方式的实现媒介。这个出现的目的是为了如果有一个组件每次创建依赖实例提供给别人时,恰好有多个其他组件里面有需要它,那么它就可以定义成子组件,需要的组件里暴露出获取子组件的依赖实例就行,如下:
@PerActivity
//@Singleton //不能与依赖的AppComponent的作用域相同,否则会报错
@Component(dependencies = AppComponent.class, modules = ActModule.class)
public interface ActivityComponent {
void inject(DependenceTestActivity DependenceTestActivity);
void inject(SubComponentTestActivity subComponentTestActivity);
//包含SubComponent,这样的话该SubComponent也可以拿到ActivityComponent中能提供的依赖。
ActSubComponent getActSubComponent();
}
@Subcomponent
@PerFragment
public interface ActSubComponent {
void inject(SubFragment subFragment);
}
1.需要在父组件的接口中声明(在接口中定义的方法对于生成的对象是可访问的)
2.能够获取父组件的所有元素(不仅仅是在接口中声明的元素)
3.子组件的实例在每次调用的时候都会被创建
4.子组件这么说 - 你的是我的,我的还是我的。父组件只能这么说 - 你的不是我的,我的是我的
三、懒加载Lazy
在宿主中使用@Inject注入依赖实例时,用Lazy<>把实例包裹起来,这样在注入完之后只是实例化了一个可以创建依赖实例的对象,真正需要使用时通过get方法获取依赖实例,据说可以减少一定的加载时间提高用户体验(主要是集中创建对象的时间):
@Inject
Lazy<Test> test;
// 使用时
Test t = test.get();
Lazy只有第一次调用get()方法时,调用构造函数实例化对象,然后将该对象缓存。以后再调用get()方法时,都会返回缓存的实例,并且不会再调用构造函数,创建实例。
四、实例注入到Set
1.注入单个实例:
@Module()
public class TestModule {
@Provides
@IntoSet
public TestModel providerModel1() {
return new TestModel("test");
}
}
2.注入子Set:
@Provides
@ElementsIntoSet
public Set<TestModel> providerModelSet() {
Set<TestModel> set = new HashSet<>();
set.add(new TestModel("test1"));
set.add(new TestModel("test2"));
return set;
}
3.使用依赖实例:
@Inject
Set<TestModel> mSetModel;
为特定集合注入数据,应对提供数据的Provides方法使用@Qualifier注解限定
五、实例注入到Map
依赖注入Map时,必须在编译时指定Map的Key。对于向Map提供元素的@Provides方法,需要使用@IntoMap,同时指定该元素的Key(例如@StringKey(“foo”)、@ClassKey(Thing.class))。
这里主要讲述简单key的注入方法,指Map的Key的数据类型为单一的某一种数据类型。
如果注入的Map的Key的类型为String、Class<?>等,在dagger.multibindings中的提供了一套标准的注解:
- ClassKey
- IntKey
- LongKey
- StringKey
@Module()
public class DrinkModule {
@Provides
@IntoMap // 指定该@Provides方法向Map提供元素
@StringKey("A") // 指定该元素在Map中所对应的的Key
public AppleBean providerApple() {
return new AppleBean("A苹果");
}
@Provides
@IntoMap
@ClassKey(DrinkActivity.class)
public AppleBean providerAppleMap() {
return new AppleBean("北京苹果");
}
}
@Inject
Map<String, AppleBean> appleByString;
@Inject
Map<Class<?>, AppleBean> appleByClass;
六、关于@MapKey
这个注解用于注入Map时自定义key:
@MapKey(unwrapValue = true)
@interface TestKey {
String value(); // 返回类型为除数组以外的任何有效的注解的成员类型
}
@Provides(type = Type.MAP)
@IntoMap
@TestKey("foo")
String provideFooKey() {
return "foo value";
}
@Provides(type = Type.MAP)
@IntoMap
@TestKey("bar")
String provideBarKey() {
return "bar value";
}
@Inject
Map<String, String> map;
map.toString() // => „{foo=foo value, bar=bar value}”
同时还可以实现组合的Map的Key,指Map的Key由多个数据类型的成员组成:
@MapKey(unwrapValue = false)
@interface MyKey {
String name();
Class<?> implementingClass();
int[] thresholds();
}
@Provides
@IntoMap
@MyKey(name = "abc", implementingClass = Abc.class, thresholds = {1, 5, 10})
static String provideAbc1510Value() {
return "foo";
}
unwrapValue默认值为true,表示key为单独类型;false时表示key为组合类型
七、配置dagger(gradle插件版本区别)
对于Gradle插件在2.3以上(推荐使用as推荐的最新稳定版本)
在module的gradle中:
dependencies {
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}
如果Gradle插件在2.3以下,借用apt插件(不推荐,apt停止维护)
在根gradle中:
dependencies {
... // 其他classpath
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //添加apt命令
}
在module的gradle中:
apply plugin: 'android-apt'
dependencies {
compile 'com.google.dagger:dagger:2.x'
apt 'com.google.dagger:dagger-compiler:2.x'
}