Dagger2的使用与理解(4)

最后一篇介绍一下不同注入器Component之间的相互依赖,这个是什么意思呢。举个例子:B注入器要注入一个Context,因为Context是Android内部的类,所以只能在BModule类提供出来,这时候发现A注入器的AModule已经提供出Context,于是我们就可以B注入器和A注入器依赖在一起,B注入器就可以复用AModule的Context。
也就是说Component之间的依赖就是复用对方的Module。
dagger2为注入器之间的依赖提供了两种方式:

  1. @Component(modules = …, dependencies = …)
  2. @Subcomponent(modules = …)

下面结合一个例子来说明这两种方式:
通常我们会有这样一个场景,Activtiy需要使用 Application的Context,但是Activity无法获得这个Context,但是在另一个组件AppComponent里面的AppModule能提供,现在我们只需要让ActivityComponent组件依赖APPComponent就可以实现。

第一种方式
注意:1.两个依赖的组件的生命周期一定要不同,也就是用不同的@Scope修饰,或者是不修饰。
2.父组件必须暴露出子组件所需要的对象(重要要!!与第二种方法的区别(第二种方式不需要显示暴露出来),否则编译出错)
下面结合代码来说明:

//这里可以用@Scope来限定生命周期,也可以不修饰
@Component(modules = AppModule.class)
public interface AppComponent {
    //必修暴露出Context
    Context provideContext();
}

@Module
public class AppModule {
    private Context appContext;

    public AppModule(Context appContext) {
        this.appContext = appContext;
    }

    //提供Context依赖
    @Provides
    public Context obtain() {
        return appContext;
    }
}

//这是Appliaction,将AppComponent 暴露出来
public class App extends Application {
    private AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
    }

    public AppComponent getAppComponent() {
        return appComponent;
    }
}

//这里还是用@Component修饰,Component注解有一个参数dependencies,指定关联的另一个Component,这里是AppComponent。
//这样ActivityComponent就与AppComponent关联在一起,AppModule就可以为ActivityComponent提供依赖。
@Component(modules = ActivityModule.class, dependencies = AppComponent.class)
public interface ActivityComponent {
    void inject(DaggerActivity daggerActivity);
}

这里ActivityModule为空实现,就不贴出代码了。
下面是DaggerActivity
public class DaggerActivity extends AppCompatActivity {
    @Inject
    Context context;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gui_view);
DaggerActivityComponent.builder().activityModule(new ActivityModule()).appComponent(getAppComponent()).build().inject(this);
    }

    private AppComponent getAppComponent() {
        return ((App) getApplication()).getAppComponent();
    }
}

注入方式为DaggerActivityComponent.builder().activityModule(new ActivityModule()).appComponent(getAppComponent()).build().inject(this);先创建DaggerActivityComponent的builder对象,再调用appComponent()传入一个AppComponent对象,最后build(),inject()。
那么appComponent()这个方法是怎么来的呢,这个是dagger2帮你生成的方法。

public final class DaggerActivityComponent implements ActivityComponent {
  private Provider<Context> provideContextProvider;
  private MembersInjector<DaggerActivity> daggerActivityMembersInjector;

  private DaggerActivityComponent(Builder builder) {  
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {  
    return new Builder();
  }

    //初始化时调用builder.appComponent.provideContext()提供Context,并再次封装成Factory赋值给provideContextProvider。
    //provideContextProvider 是DaggerActivityComponent的成员变量,它传给注入器初始化,在注入时就会将provideContextProvider里的Context提供出来。
  private void initialize(final Builder builder) {  
    this.provideContextProvider = new Factory<Context>() {
      @Override public Context get() {
        Context provided = builder.appComponent.provideContext();
        if (provided == null) {
          throw new NullPointerException("Cannot return null from a non-@Nullable component method");
        }
        return provided;
      }
    };
    this.daggerActivityMembersInjector = DaggerActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideContextProvider);
  }

  @Override
  public void inject(DaggerActivity daggerActivity) {  
    daggerActivityMembersInjector.injectMembers(daggerActivity);
  }

  public static final class Builder {
    private ActivityModule activityModule;
    private AppComponent appComponent;

    private Builder() {  
    }

    public ActivityComponent build() {  
      if (activityModule == null) {
        this.activityModule = new ActivityModule();
      }
      if (appComponent == null) {
        throw new IllegalStateException("appComponent must be set");
      }
      return new DaggerActivityComponent(this);
    }

    public Builder activityModule(ActivityModule activityModule) {  
      if (activityModule == null) {
        throw new NullPointerException("activityModule");
      }
      this.activityModule = activityModule;
      return this;
    }

      //此方法是dagger2自动生成的,将关联的Component添加进来,
      作为builder的属性之一。
    public Builder appComponent(AppComponent appComponent) {  
      if (appComponent == null) {
        throw new NullPointerException("appComponent");
      }
      this.appComponent = appComponent;
      return this;
    }
  }
}

所以本质上来讲就是让ActivityComponent实现类持有AppComponent实现类的引用,ActivityComponent实现类可以调用AppComponent实现类的属性和方法。
第二种方式

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    ActivityComponent plus(ActivityModule module);
}

//AppComponent的Module,里面能提供Context依赖
@Module
public class AppModule {
    private Context appContext;

    public AppModule(Context appContext) {
        this.appContext = appContext;
    }
    @Provides
    @Singleton
    public Context obtain() {
        return appContext;
    }
}

//在Application注入
public class App extends Application {
    private AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
    }

    //获得AppComponent
    public AppComponent getAppComponent() {
        return appComponent;
    }
}
//注意这里用@Subcomponent而不是用@Component
@ActivityScope
@Subcomponent(modules = ActivityModule.class)
public interface ActivityComponent {
    void inject(DaggerActivity daggerActivity);
}

这里ActivityModule为空实现,就不贴出代码了。

public class DaggerActivity extends AppCompatActivity {

    //注入Context对象
    @Inject
    Context context;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gui_view);
        getAppComponent().plus(new ActivityModule()).inject(this);
    }

    private AppComponent getAppComponent() {
        return ((App) getApplication()).getAppComponent();
    }
}

这里首先在AppComponent接口里添加一个新的方法, ActivityComponent plus(ActivityModule module),必须是这种格式返回值是Component(用@Subcomponent修饰),参数必须Module类型或者不写参数,否则编译会出错。这里plus名字和inject名字一样,可以任取函数名,一般用plus。这个方法表示AcitivityComponent注入时可以从AppModule里找依赖。
通常是在Application里,将AppComponent暴露出来,

appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();

public AppComponent getAppComponent() {
        return appComponent;
}

在Activity时候注入,注入时写法如下

//这里就调用了plus方法与AppComponent关联
getAppComponent().plus(new ActivityModule()).inject(this);

private AppComponent getAppComponent() {
        return ((App) getApplication()).getAppComponent();
}

这样在注入Activity 的 Context时候,就会从AppModule里面去找,因为ActivityModule没有Context依赖,也说明了这两个Component关联在一起了,可以复用AppModule的依赖。注意:如果两个Module都有Context,这时候必须用之前用过的@Named和@Qualifier两个注解去区分是哪一个Context,否则编译出错。
ActivityComponent plus(ActivityModule module) 这个方法的本质实质上是将ActivityComponent的实现类ActivityComponentImpl作为AppComponent的实现类DaggerAppComponent的子类。

public final class DaggerAppComponent implements AppComponent {
  private Provider<Context> obtainProvider;

  private DaggerAppComponent(Builder builder) {  
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {  
    return new Builder();
  }

  private void initialize(final Builder builder) {  
    this.obtainProvider = ScopedProvider.create(AppModule_ObtainFactory.create(builder.appModule));
  }

//重写的plus方法,里面new ActivityComponentImpl()。
//如果plus有参数就传入module,new ActivityComponentImpl(module),无参数就new ActivityComponentImpl()。
  @Override
  public ActivityComponent plus(ActivityModule module) {  
    return new ActivityComponentImpl(module);
  }

  public static final class Builder {
    private AppModule appModule;

    private Builder() {  
    }

    public AppComponent build() {  
      if (appModule == null) {
        throw new IllegalStateException("appModule must be set");
      }
      return new DaggerAppComponent(this);
    }

    public Builder appModule(AppModule appModule) {  
      if (appModule == null) {
        throw new NullPointerException("appModule");
      }
      this.appModule = appModule;
      return this;
    }
  }

//内部类,持有外部类的this引用,因而可以直接调用外部类AppComponent的方法和属性
  private final class ActivityComponentImpl implements ActivityComponent {
    private final ActivityModule activityModule;
    private MembersInjector<DaggerActivity> daggerActivityMembersInjector;

    private ActivityComponentImpl(ActivityModule activityModule) {  
      if (activityModule == null) {
        throw new NullPointerException();
      }
      this.activityModule = activityModule;
      initialize();
    }

  //daggerActivityMembersInjector注入器的实现传入DaggerAppComponent.this.obtainProvider。
  //obtainProvider就是外部类的Context依赖提供者,为Activity的注入提供了Context。
    private void initialize() { 
      this.daggerActivityMembersInjector = DaggerActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), DaggerAppComponent.this.obtainProvider);
    }

  //注入将Context注入进去
    @Override
    public void inject(DaggerActivity daggerActivity) {  
      daggerActivityMembersInjector.injectMembers(daggerActivity);
    }
  }
}

差不多了,断断续续把dagger2系列写完啦,大家看看就好,不喜勿喷。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值