@Singleton
@Singleton
注解言简意赅,就是单例的意思。也就是说,注入的依赖是个单例对象。
在 BicycleModules#getBicycle()
添加 @Singleton
注解, BicycleModules
初始代码见这里
@Module
public class BicycleModules {
@Provides
@Singleton
public Bicycle getBicycle(){
return new Bicycle();
}
}
编译报错:
Error:(14, 8) 错误: [Dagger/IncompatiblyScopedBindings] com.oliver.test.bicycle.Mobai (unscoped) may not reference scoped bindings:
@Provides @Singleton com.oliver.test.bicycle.Bicycle com.oliver.test.bicycle.BicycleModules.getBicycle()
不兼容的 Scope 绑定, 说是 Mobai 没有引用 scope 绑定
也就是说,假设 @Component
引用的 @Module
有提供单例对象, @Component
也必须四单例的,即也需要被 @Singleton
注解标注。
比较 @Component
没有添加 @Singleton
注解的生成代码,不同之处在与:
private void initialize(final Builder builder) {
this.getBicycleProvider =
DoubleCheck.provider(BicycleModules_GetBicycleFactory.create(builder.bicycleModules));
}
public static <P extends Provider<T>, T> Provider<T> provider(P delegate) {
checkNotNull(delegate);
if (delegate instanceof DoubleCheck) {
return delegate;
}
return new DoubleCheck<T>(delegate);
}
private DoubleCheck(Provider<T> provider) {
assert provider != null;
this.provider = provider;
}
可以看出,DoubleCheck
是对 BicycleModules_GetBicycleFactory
再一层封装,并将 BicycleModules_GetBicycleFactory
赋值给 DoubleCheck
的成员变量 provider
。那怎么就保证了单例呢?看看注入依赖的地方:
@Override
public void inject(MainActivity mainActivity) {
injectMainActivity(mainActivity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectMBicycle(instance, getBicycleProvider.get());
return instance;
}
也就是说,getBicycleProvider.get()
获取到的对象是单例的,再回过头看 DoubleCheck#get()
:
public T get() {
Object result = instance;
if (result == UNINITIALIZED) {
synchronized (this) {
result = instance;
if (result == UNINITIALIZED) {
result = provider.get();
instance = reentrantCheck(instance, result);
/* Null out the reference to the provider. We are never going to need it again, so we
* can make it eligible for GC. */
provider = null;
}
}
}
return (T) result;
}
可以看出,这是一个双重锁单例机制,通过双重锁保证了 result
的唯一性,再次获取得到的是同一个对象。但是,getBicycleProvider
是 @Component
生成类的成员变量,也就是说,当我们再次 new
一个 DaggerMobai
对象时,获取到的依赖就不再是单例了。
@Singleton
只是局部的单例,单例效果只在同一个 @Component
内有效,在不同的 @Component
对象是无效的。例如,我们再两个 Activity
中调用以下代码:
DaggerMobai.builder()
.bicycleModules(new BicycleModules())
.build()
.inject(this);
Log.d("MainActivity", mBicycle.toString());
打印结果:
MainActivity: com.oliver.test.bicycle.Bicycle@1069ab85
MainActivity: com.oliver.test.bicycle.Bicycle@33859363
因为调用 build()
方法会再次 new DaggerMobai()
,故而得到的结果非单例。
那怎样确定一个全局单例呢?其实也简单,那就是想办法将 @Component
的作用域与 Application
绑定,这样保证了 @Component
的全局唯一性,得到的依赖自然也就全局唯一。
首先,定义 @Module
来提供依赖,这里是 Bicycle
对象:
@Module
public class AppModule {
@Singleton
@Provides
public Bicycle providerBicycle(){
return new Bicycle();
}
}
接着,定义 @Component
:
@Singleton
@Component(modules = {AppModule.class})
public abstract class AppComponent {
// 提供 Bicycle 对象
// 该方法是必须的,且是 public 的
public abstract Bicycle providerBicycle();
}
编译,生成 DaggerAppComponent
和 AppModule_ProviderBicycleFactory
:
public final class DaggerAppComponent extends AppComponent {
private Provider<Bicycle> providerBicycleProvider;
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static AppComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.providerBicycleProvider =
DoubleCheck.provider(AppModule_ProviderBicycleFactory.create(builder.appModule));
}
@Override
public Bicycle providerBicycle() {
return providerBicycleProvider.get();
}
public static final class Builder {
private AppModule appModule;
private Builder() {}
public AppComponent build() {
if (appModule == null) {
this.appModule = new AppModule();
}
return new DaggerAppComponent(this);
}
public Builder appModule(AppModule appModule) {
this.appModule = Preconditions.checkNotNull(appModule);
return this;
}
}
}
public final class AppModule_ProviderBicycleFactory implements Factory<Bicycle> {
private final AppModule module;
public AppModule_ProviderBicycleFactory(AppModule module) {
this.module = module;
}
@Override
public Bicycle get() {
return provideInstance(module);
}
public static Bicycle provideInstance(AppModule module) {
return proxyProviderBicycle(module);
}
public static AppModule_ProviderBicycleFactory create(AppModule module) {
return new AppModule_ProviderBicycleFactory(module);
}
public static Bicycle proxyProviderBicycle(AppModule instance) {
return Preconditions.checkNotNull(
instance.providerBicycle(), "Cannot return null from a non-@Nullable @Provides method");
}
}
和上面一致,其实就是使用双重锁机制保证单例。但接下来,需要将该 DaggerAppComponent
实例缓存在 Application
中,保证其全局唯一:
public class MyApp extends Application {
private static AppComponent mAppComponent;
@Override
public void onCreate() {
super.onCreate();
// 唯一的实例
mAppComponent = DaggerAppComponent.create();
}
public static AppComponent getAppComponent() {
return mAppComponent;
}
}
接下来需要使用 AppComponent
,这里就需要用到 @Component
的另一个字段 -- dependencies:
@Component(dependencies = {AppComponent.class})
public interface Mobai {
void inject(MainActivity mainActivity);
void inject(AActivity aActivity);
}
再次编译,报错:
Error:(18, 1) 错误: com.oliver.test.bicycle.Mobai (unscoped) cannot depend on scoped components:
@Singleton com.oliver.test.app.AppComponent
就是说 Mobai
没有被 @Scope
标注,不能够依赖 AppComponent
。这里要说一下, @Scope
表示注入对象的作用范围, @Singleton
之所以有单例的效果,就是因为被 @Scope
注解标注 ,拥有其特性。
添加 @Singleton
,再次编译:
@Singleton
@Component(modules = {BicycleModules.class} ,dependencies = {AppComponent.class})
public interface Mobai {
void inject(MainActivity mainActivity);
void inject(AActivity aActivity);
}
再次报错:
Error:(19, 1) 错误: This @Singleton component cannot depend on scoped components:
@Singleton com.oliver.test.app.AppComponent
即被@Singleton
标注的 @Component
不能依赖于另一个被 @Singleton
标注的 @Component
。也就是说,需要自定义一个新的 @Scope
,仿照 @Singleton
创建注解 @ActivityScope:
@Scope
@Documented
@Retention(RUNTIME)
public @interface ActivityScope {
}
并使用在 Mobai
上:
@ActivityScope
@Component(modules = {BicycleModules.class} ,dependencies = {AppComponent.class})
public interface Mobai {
void inject(MainActivity mainActivity);
void inject(AActivity aActivity);
}
再次编译,通过。再次运行程序,在两个不同的 Activity
添加如下代码:
DaggerMobai.builder()
.appComponent(MyApp.getAppComponent())
.build()
.inject(this);
Log.d("MainActivity", mBicycle.toString());
得到结果:
MainActivity: com.oliver.test.bicycle.Bicycle@1069ab85
MainActivity: com.oliver.test.bicycle.Bicycle@1069ab85
至此,全局单例就得到了。
根据调用来看,全局单例的形成肯定和这句代码息息相关:
appComponent(MyApp.getAppComponent())
因为在 DaggerAppComponent
中得到的 Bicycle
单例的
private void initialize(final Builder builder) {
this.providerBicycleProvider =
DoubleCheck.provider(AppModule_ProviderBicycleFactory.create(builder.appModule));
}
@Override
public Bicycle providerBicycle() {
return providerBicycleProvider.get();
}
而 DaggerAppComponent
在 Application
中初始化,也保证了其唯一性。故而:
DaggerMobai.builder()
.appComponent(MyApp.getAppComponent())
.build()
.inject(this);
应该是由 appComponent(MyApp.getAppComponent())
提供依赖,保证唯一。具体看 DaggerMobai
源码:
public final class DaggerMobai implements Mobai {
private AppComponent appComponent;
private DaggerMobai(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.appComponent = builder.appComponent;
}
@Override
public void inject(MainActivity mainActivity) {
injectMainActivity(mainActivity);
}
@Override
public void inject(AActivity aActivity) {
injectAActivity(aActivity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectMBicycle(
instance,
Preconditions.checkNotNull(
appComponent.providerBicycle(),
"Cannot return null from a non-@Nullable component method"));
return instance;
}
private AActivity injectAActivity(AActivity instance) {
AActivity_MembersInjector.injectMBicycle(
instance,
Preconditions.checkNotNull(
appComponent.providerBicycle(),
"Cannot return null from a non-@Nullable component method"));
return instance;
}
public static final class Builder {
private AppComponent appComponent;
private Builder() {}
// 可以看到,appComponent()方法是必须调用的
public Mobai build() {
if (appComponent == null) {
throw new IllegalStateException(AppComponent.class.getCanonicalName() + " must be set");
}
return new DaggerMobai(this);
}
@Deprecated
public Builder bicycleModules(BicycleModules bicycleModules) {
Preconditions.checkNotNull(bicycleModules);
return this;
}
public Builder appComponent(AppComponent appComponent) {
this.appComponent = Preconditions.checkNotNull(appComponent);
return this;
}
}
}
通过注入代码可知,确实是由 AppComponent
来提供依赖,这也正是需要在 AppComponent
中存在提供依赖的方法的原因。
private AActivity injectAActivity(AActivity instance) {
AActivity_MembersInjector.injectMBicycle(
instance,
Preconditions.checkNotNull(
appComponent.providerBicycle(),
"Cannot return null from a non-@Nullable component method"));
return instance;
}
小结:
-
@Singleton
注解只是局部单例 - 如果
@Module
中使用了@Singleton
,那么对应的@Component
中也需要被@Singleton
标注 -
@Component
依赖的另一个@Component
使用了@Scope
,本@Component
不能再使用相同的@Scope
或者是不使用@Scope
,而是需要重新定义一个。 - 定义全局单例依赖,需要在
AppComponent
中定义提供依赖的方法
@Named
假设一个类,我们需要两个不同的对象,那么,在 @Module
中可以这样:
@Module
public class CarModules {
@Provides
public Car providerCarA() {
return new Car("本田");
}
@Provides
public Car providerCarB() {
return new Car("兰博基尼");
}
}
Car
:
public class Car {
@Inject
public Car(String info) {
System.out.println("I'm a Car -- " + info);
}
}
可以看出,存在了两个方法来提供不同的 Car
实例。编译,报错:
Error:(17, 10) 错误: [Dagger/DuplicateBindings] com.oliver.test.car.Car is bound multiple times:
@Provides com.oliver.test.car.Car com.oliver.test.car.CarModules.providerCarA()
@Provides com.oliver.test.car.Car com.oliver.test.car.CarModules.providerCarB()
com.oliver.test.car.Car is injected at
com.oliver.test.MainActivity.mCarA
com.oliver.test.MainActivity is injected at
com.oliver.test.car.Ofo.inject(com.oliver.test.MainActivity)
这是因为提供了两个 Car
对象,然后在 MainActivity
中也有两个 Car
实例等待注入,Dagger
并不知道两者之间的对应关系是怎样的?
public class MainActivity extends AppCompatActivity {
@Inject
@Named("A")
Car mCarA;
@Inject
@Named("B")
Car mCarB;
}
Dagger
不知道哪个生成的 Car
该注入到mCarA
, 哪个该注入到mCarB
,故而报错。解决这个问题,就要让Dagger
知道他们的对应关系。这里有两个方法可以办到,分别是 @Named
和 @Qualifier
。其实, @Named
就是被 @Qualifier
所标注的,故而也就一种方法。
先看看 @Named
的使用:
@Module
public class CarModules {
@Provides
@Named("A")
public Car providerCarA() {
return new Car("本田");
}
@Provides
@Named("B")
public Car providerCarB() {
return new Car("兰博基尼");
}
}
在 MainActivity
中:
public class MainActivity extends AppCompatActivity {
@Inject
@Named("A")
Car mCarA;
@Inject
@Named("B")
Car mCarB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerOfo.builder().build().inject(this);
}
}
编译运行,打印结果如下:
System.out: I'm a Car -- 本田
System.out: I'm a Car -- 兰博基尼
@Qualifier
标识限定符注释,@Named
其实就是一个@Qualifier
。
现在通过定义新的 @Qualifier
来改造上面的例子:
首先定义两个 @Qualifier
,分别为 CarA
和 CarB:
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface CarA {
}
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface CarB {
}
然后在依赖提供处和依赖需求处使用:
@Module
public class CarModules {
@Provides
@CarA
public Car providerCarA() {
return new Car("本田");
}
@Provides
@CarB
public Car providerCarB() {
return new Car("兰博基尼");
}
}
public class MainActivity extends AppCompatActivity {
@Inject
@CarA
Car mCarA;
@Inject
@CarB
Car mCarB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerOfo.builder().build().inject(this);
}
}
编译运行,打印结果如下:
System.out: I'm a Car -- 本田
System.out: I'm a Car -- 兰博基尼
@Lazy
@Lazy
起到一个懒加载的作用,也就是当你需要该依赖的时候,才通过 get()
方法获取,第一次获取会进行 new
操作,接下来就会取上次的缓存直接返回。通过源码:
public class MainActivity extends AppCompatActivity {
@Inject
@CarA
Lazy<Car> mCarLazyA;
@Inject
@CarB
Lazy<Car> mCarLazyB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerOfo.builder().build().inject(this);
Log.d("MainActivity", "mCarLazyA.get():" + mCarLazyA.get());
Log.d("MainActivity", "mCarLazyB.get():" + mCarLazyB.get());
}
}
DaggerOfo
注入源码:
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectMCarLazyA(instance, DoubleCheck.lazy(providerCarAProvider));
MainActivity_MembersInjector.injectMCarLazyB(instance, DoubleCheck.lazy(providerCarBProvider));
return instance;
}
由上可知,对依赖使用 Lazy<T>
,其实真正的赋值类型是 DoubleCheck
,也就是调用 get()
方法才能获取到真正的 Car
对象,并且保证了对象的复用。
@Subcomponent
- 使用
1、定义一个被 @Module
标注的接口
@Module
public class BicycleModules {
}
由于这里测试的是 @Subcomponent 注解,注入由 @Component 提供的依赖,故而该接口不写任何方法。当然,假设需要自身提供任何依赖,也可以加上 @provider 方法
2、定义一个被 @Subcomponent
标注的接口
@Subcomponent(modules = {BicycleModules.class})
public interface Ofo {
void inject(MainActivity activity);
}
3、将该接口使用在被 @Component
标注的类中
@Component(modules = {AppModule.class})
public abstract class AppComponent {
public abstract Bicycle providerBicycle();
public abstract Ofo addOfoSub(BicycleModules bicycleModules);
}
4、在 MainActivity
中使用
@Inject
Bicycle mBicycle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerAppComponent.builder().build().addOfoSub(new BicycleModules()).inject(this);
Log.d("MainActivity", "mBicycle:" + mBicycle);
}
被 @Subcomponent
标注的类不会生成 DaggerXxxComponent
类,但是会在使用他的 @Component
类中生成对应的 名字+Impl
实现类,例如,Ofo
生成类为 OfoImpl
.
public final class DaggerAppComponent extends AppComponent {
private Provider<Bicycle> providerBicycleProvider;
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static AppComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.providerBicycleProvider =
DoubleCheck.provider(AppModule_ProviderBicycleFactory.create(builder.appModule));
}
@Override
public Bicycle providerBicycle() {
return providerBicycleProvider.get();
}
@Override
public Ofo addOfoSub(BicycleModules bicycleModules) {
return new OfoImpl(bicycleModules);
}
public static final class Builder {
private AppModule appModule;
private Builder() {
}
public AppComponent build() {
if (appModule == null) {
this.appModule = new AppModule();
}
return new DaggerAppComponent(this);
}
public Builder appModule(AppModule appModule) {
this.appModule = Preconditions.checkNotNull(appModule);
return this;
}
}
private final class OfoImpl implements Ofo {
private OfoImpl(BicycleModules bicycleModules) {
}
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectMBicycle(
instance, DaggerAppComponent.this.providerBicycleProvider.get());
return instance;
}
}
}
当我们在 MainActivity
中调用这句代码时:
DaggerAppComponent.builder().build().addOfoSub(new BicycleModules()).inject(this);
可以在 DaggerAppComponent#OfoImpl
中看到,会将 @Component
提供的 Bicycle
对象赋值给 MainActivity
的依赖变量 mBicycle
.
网友评论