美文网首页
dagger2(三)

dagger2(三)

作者: Mr_468 | 来源:发表于2016-09-29 15:45 被阅读0次

    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是单例的。

    相关文章

      网友评论

          本文标题:dagger2(三)

          本文链接:https://www.haomeiwen.com/subject/pixkyttx.html