Scope
Scope标注是用来自定义标注接口的,被scope标注的接口与系统自带的singleton是一样的,创建不同的接口是为了用类名作区分。它们都是在定义从module中注入的实例的生命周期,这个生命周期和与它有相同标注的component生命周期一致。(即在同一个component对象中,被scope类标注的对象是单例的)
先看系统自带的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();
}
}
获取各对象看看有什么区别。
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的生命周期内是单例的?因为component生命周期内userprovider是单例的。
网友评论