dagger2(三)

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 contextProvider;
private Provider userProvider;
private Provider 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 implements Provider {
  private static final Object UNINITIALIZED = new Object();

  private final Factory factory;
  private volatile Object instance = UNINITIALIZED;

  private ScopedProvider(Factory 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  Provider create(Factory factory) {
    if (factory == null) {
      throw new NullPointerException();
    }
    return new ScopedProvider(factory);
  }
}

很明显,它的get方法进行了单例处理。
为什么在component的生命周期内是单例的?因为component生命周期内userprovider是单例的。

你可能感兴趣的:(dagger2(三))