Scope
Scope標注是用來自定義標注接口的,被scope標注的接口與系統(tǒng)自帶的singleton是一樣的快耿,創(chuàng)建不同的接口是為了用類名作區(qū)分剩盒。它們都是在定義從module中注入的實例的生命周期猪半,這個生命周期和與它有相同標注的component生命周期一致色冀。(即在同一個component對象中,被scope類標注的對象是單例的)
先看系統(tǒng)自帶的singleton
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
再看我們自定義的類挪略,除了類名其余完全一致历帚。
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyScope {}
用在Component和module的獲取User方法上滔岳。
@MyScope
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
void inject(MyApp app);
Context getContext();
User getUser();
Car getCar();
}
@Module
public class ApplicationModule {
Context context;
public ApplicationModule(MyApp app){
this.context = app;
}
@Provides
Context context(){
return this.context;
}
@Provides
@MyScope
User user() {
return new User();
}
@Provides
Car car(){
return new Car();
}
}
獲取各對象看看有什么區(qū)別。
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
ApplicationComponent component1 = DaggerApplicationComponent.builder().
applicationModule(new ApplicationModule(this)).build();
ApplicationComponent component2 = DaggerApplicationComponent.builder().
applicationModule(new ApplicationModule(this)).build();
User user1 = component1.getUser();
User user2 = component1.getUser();
User user2_1 = component2.getUser();
User user2_2 = component2.getUser();
Car car1 = component1.getCar();
Car car2 = component1.getCar();
Context context1 = component1.getContext();
Context context2 = component1.getContext();
Log.e("dagger2",
"component1: " + component1.hashCode()
+ " user1: " + user1.hashCode()
+ " user2_1: " + user2_1.hashCode()
+ " car1: " + car1.hashCode()
+ "context1: " + context1.hashCode());
Log.e("dagger2",
"component2: " + component2.hashCode()
+ " user2: " + user2.hashCode()
+ " user2_2: " + user2_2.hashCode()
+ " car2: " + car2.hashCode()
+ "context2: " + context2.hashCode());
}
}
component1: 1126017480 user1: 1126022368 user2_1: 1126022384 car1: 1126022400 context1: 1125985360
component2: 1126022272 user2: 1126022368 user2_2: 1126022384 car2: 1126022416 context2: 1125985360
log里可以看出同一個對象里被providers標注的user里是單例的挽牢,沒有被標注的car不是單例的谱煤,但是沒有被標注的context是單例。context對象來自module中的context方法禽拔,方法返回的是app對象刘离,在同一個app中只有一個app對象,所以context是單例的睹栖。
為什么被providers標注的user也是單例的硫惕?看看生成的代碼
public final class DaggerApplicationComponent implements ApplicationComponent {
private Provider<Context> contextProvider;
private Provider<User> userProvider;
private Provider<Car> carProvider;
private DaggerApplicationComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
private void initialize(final Builder builder) {
this.contextProvider = ApplicationModule_ContextFactory.create(builder.applicationModule);
this.userProvider = ScopedProvider.create(ApplicationModule_UserFactory.create(builder.applicationModule));
this.carProvider = ApplicationModule_CarFactory.create(builder.applicationModule);
}
@Override
public void inject(MyApp app) {
MembersInjectors.noOp().injectMembers(app);
}
@Override
public Context getContext() {
return contextProvider.get();
}
@Override
public User getUser() {
return userProvider.get();
}
@Override
public Car getCar() {
return carProvider.get();
}
public static final class Builder {
private ApplicationModule applicationModule;
private Builder() {
}
public ApplicationComponent build() {
if (applicationModule == null) {
throw new IllegalStateException("applicationModule must be set");
}
return new DaggerApplicationComponent(this);
}
public Builder applicationModule(ApplicationModule applicationModule) {
if (applicationModule == null) {
throw new NullPointerException("applicationModule");
}
this.applicationModule = applicationModule;
return this;
}
}
}
user是由userprovider的get方法獲取的。userprovider是ScopeProvider.create生成的野来,追進代碼恼除。
public final class ScopedProvider<T> implements Provider<T> {
private static final Object UNINITIALIZED = new Object();
private final Factory<T> factory;
private volatile Object instance = UNINITIALIZED;
private ScopedProvider(Factory<T> factory) {
assert factory != null;
this.factory = factory;
}
@SuppressWarnings("unchecked") // cast only happens when result comes from the factory
@Override
public T get() {
// double-check idiom from EJ2: Item 71
Object result = instance;
if (result == UNINITIALIZED) {
synchronized (this) {
result = instance;
if (result == UNINITIALIZED) {
instance = result = factory.get();
}
}
}
return (T) result;
}
/** Returns a new scoped provider for the given factory. */
public static <T> Provider<T> create(Factory<T> factory) {
if (factory == null) {
throw new NullPointerException();
}
return new ScopedProvider<T>(factory);
}
}
很明顯,它的get方法進行了單例處理曼氛。
為什么在component的生命周期內(nèi)是單例的豁辉?因為component生命周期內(nèi)userprovider是單例的。