在 Dagger2 中,@Singleton 注解的作用是什么?
In Dagger2, what is the purpose of the @Singleton annotation?
假设我们有一个 class Counter
:
public class Counter {
private int count;
public Counter() {
count = 0;
}
public int getCount() {
return count;
}
public void count() {
count++;
}
}
以及提供计数器的ApplicationModule
:
@Module
public class ApplicationModule {
private Context context;
private Counter counter;
public ApplicationModule(Context context) {
this.context = context;
counter = new Counter();
}
@Provides @Singleton
public Counter provideCounter() {
return counter;
}
}
通过将 @Singleton
注释添加到 provideCounter()
方法,您是否指定只提供一个 Counter 对象?
如果我们提供两个 Counter
对象:
@Module
public class ApplicationModule {
private Context context;
private Counter numberOfTimesButtonAWasPressed;
private Counter numberOfTimesButtonBWasPressed;
public ApplicationModule(Context context) {
this.context = context;
numberOfTimesButtonAWasPressed = new Counter();
numberOfTimesButtonBWasPressed = new Counter();
}
@Provides @Named("buttonACounter")
public Counter provideButtonACounter() {
return numberOfTimesButtonAWasPressed;
}
@Provides @Named("buttonBCounter")
public Counter provideButtonBCounter() {
return numberOfTimesButtonBWasPressed;
}
}
@Singleton
注释是否非法?
@Singleton
将确保组件中只有 一个同类。
所以是的,将其设置为单例将导致在所有地方都使用相同的对象使用此组件。如果您创建第二个组件,也会创建第二个计数器——它是一个不同的对象图。
@Provides @Named("buttonBCounter")
public Counter provideButtonBCounter() {
return numberOfTimesButtonBWasPressed;
}
这表示,当我需要一个名为 buttonBCounter
的 Counter
调用此方法时,但是 总是会 return 编辑同一个对象因为你的模块构造函数:
// don't do this.
public ApplicationModule(Context context) {
numberOfTimesButtonAWasPressed = new Counter();
numberOfTimesButtonBWasPressed = new Counter();
}
即使你没有用 @Singleton
注释它,这个方法也会 像 一样,因为你将对象保存在你的模块中并且 return 每次调用相同的实例。
// do it right
@Singleton @Provides @Named("buttonBCounter")
public Counter provideButtonBCounter() {
return new Counter();
}
这将与上面的代码产生相同的效果,尽管该方法只会被调用一次,然后 dagger 将处理适当的对象缓存。
使用 dagger,真正让 dagger 负责对象创建可能是个好主意。
然后您甚至可以继续做类似...
// if you have an @Inject annotated constructor
@Singleton @Provides @Named("buttonBCounter")
public Counter provideButtonBCounter(Counter counter) {
return counter;
}
...这将使您充分利用构造函数注入。如果参数发生变化,则无需更新。
此外,如果有疑问,只需添加日志记录语句 and/or 附加调试器。没什么神奇的,快去试试吧!
假设我们有一个 class Counter
:
public class Counter {
private int count;
public Counter() {
count = 0;
}
public int getCount() {
return count;
}
public void count() {
count++;
}
}
以及提供计数器的ApplicationModule
:
@Module
public class ApplicationModule {
private Context context;
private Counter counter;
public ApplicationModule(Context context) {
this.context = context;
counter = new Counter();
}
@Provides @Singleton
public Counter provideCounter() {
return counter;
}
}
通过将 @Singleton
注释添加到 provideCounter()
方法,您是否指定只提供一个 Counter 对象?
如果我们提供两个 Counter
对象:
@Module
public class ApplicationModule {
private Context context;
private Counter numberOfTimesButtonAWasPressed;
private Counter numberOfTimesButtonBWasPressed;
public ApplicationModule(Context context) {
this.context = context;
numberOfTimesButtonAWasPressed = new Counter();
numberOfTimesButtonBWasPressed = new Counter();
}
@Provides @Named("buttonACounter")
public Counter provideButtonACounter() {
return numberOfTimesButtonAWasPressed;
}
@Provides @Named("buttonBCounter")
public Counter provideButtonBCounter() {
return numberOfTimesButtonBWasPressed;
}
}
@Singleton
注释是否非法?
@Singleton
将确保组件中只有 一个同类。
所以是的,将其设置为单例将导致在所有地方都使用相同的对象使用此组件。如果您创建第二个组件,也会创建第二个计数器——它是一个不同的对象图。
@Provides @Named("buttonBCounter")
public Counter provideButtonBCounter() {
return numberOfTimesButtonBWasPressed;
}
这表示,当我需要一个名为 buttonBCounter
的 Counter
调用此方法时,但是 总是会 return 编辑同一个对象因为你的模块构造函数:
// don't do this.
public ApplicationModule(Context context) {
numberOfTimesButtonAWasPressed = new Counter();
numberOfTimesButtonBWasPressed = new Counter();
}
即使你没有用 @Singleton
注释它,这个方法也会 像 一样,因为你将对象保存在你的模块中并且 return 每次调用相同的实例。
// do it right
@Singleton @Provides @Named("buttonBCounter")
public Counter provideButtonBCounter() {
return new Counter();
}
这将与上面的代码产生相同的效果,尽管该方法只会被调用一次,然后 dagger 将处理适当的对象缓存。
使用 dagger,真正让 dagger 负责对象创建可能是个好主意。
然后您甚至可以继续做类似...
// if you have an @Inject annotated constructor
@Singleton @Provides @Named("buttonBCounter")
public Counter provideButtonBCounter(Counter counter) {
return counter;
}
...这将使您充分利用构造函数注入。如果参数发生变化,则无需更新。
此外,如果有疑问,只需添加日志记录语句 and/or 附加调试器。没什么神奇的,快去试试吧!