Dagger2的使用与理解(4)

来源:互联网 发布:电子发票 用软件开 编辑:程序博客网 时间:2024/06/05 18:11

最后一篇介绍一下不同注入器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();}@Modulepublic 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为空实现,就不贴出代码了。下面是DaggerActivitypublic 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依赖@Modulepublic 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系列写完啦,大家看看就好,不喜勿喷。

原创粉丝点击