Dagger2中可以很方便的实现单例,但注意这个单例是一个Component作用域范围内的单例,而这个范围,需要上层定义@Scope注解。默认可以使用@Singleton注解,也可以使用自定义其他名称的注解,自定义时参照@Singleton即可,例如@Abc都没有问题,该注解没有特殊作用,只是起标记作用,因此命名与范围相符合更好。
例如可以取如下范围单例:
1.@ApplicationSingleton:进程级别单例
2.@ActivitySingleton:页面级别的单例
单例实现步骤
Dagger2实现单例分2步:
- 给对应的Component添加范围注解
例如CoffeeShopComponent使用自定的范围注解@ActivitySingleton,代码如下:
@Subcomponent(modules = {SubModule.class})
@ActivitySingleton
public interface CoffeeShopComponent {
@Subcomponent.Builder
interface Builder {
CoffeeShopComponent build();
}
void inject(Street street);
}
- 给该Component依赖的Module中提供的对象方法加上该范围注解。
例如期望Logger是单例的,则在Logger的providers方法上,增加和Component或父Component一样的范围注解,表示在Component或父Component实例内是单例的。
@Module
public class SubModule {
@ActivitySingleton
@Provides
public Logger providerLogger(Retrofit retrofit) {
return new Logger(retrofit);
}
}
自动注入的对象,直接在类上设置@Scope类型注解,即可设置单例范围,例如:
@ActivitySingleton
public class TestData {
@Inject
public TestData() {
System.out.println("abc");
}
}
注意
如果注入的对象的Scope范围与Component以及父Component的范围都不符合,则会报错:(unscoped) may not reference scoped bindings
如何实现Activity内单例
Activity内单例也就是同一个Activity内部的注入对象,是同一个。因此需要以下2步:
- 将Activity内部的Component保持只有1个实例,且与其他Activity中的Component为不同的实例
- 将注入对象设置的@Scope类型注解与Component一致