Dagger2的使用与理解(4)
来源:互联网 发布:电子发票 用软件开 编辑:程序博客网 时间:2024/06/05 18:11
最后一篇介绍一下不同注入器Component之间的相互依赖,这个是什么意思呢。举个例子:B注入器要注入一个Context,因为Context是Android内部的类,所以只能在BModule类提供出来,这时候发现A注入器的AModule已经提供出Context,于是我们就可以B注入器和A注入器依赖在一起,B注入器就可以复用AModule的Context。
也就是说Component之间的依赖就是复用对方的Module。
dagger2为注入器之间的依赖提供了两种方式:
- @Component(modules = …, dependencies = …)
- @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系列写完啦,大家看看就好,不喜勿喷。
- Dagger2的使用与理解(4)
- Dagger2的使用与理解(1)
- Dagger2的使用与理解(2)
- Dagger2的使用与理解(3)
- Dagger2的了解与使用
- Dagger2 学习与理解
- Dagger2自己的理解
- android框架学习篇-Dagger2的理解与应用
- 一些关于dagger2的理解
- 我所理解的Dagger2
- 我所理解的Dagger2
- dagger2框架的学习理解
- 我对Dagger2的理解
- Dagger2的使用
- 对Dagger2的使用
- Dagger2的使用
- Dagger2的简单使用
- Dagger2的简单使用
- CentOS7 安装配置 MySQL5.7.18
- 文章标题
- LinkedHashMap、HashMap、Hashtable、TreeMap的比较使用
- 快速排序--基准定位,分而治之
- 如何生成war包
- Dagger2的使用与理解(4)
- Ubuntu下安装tools
- STL系列之一 deque双向队列
- try-catch-finally
- ural1109Conference(最小边覆盖)
- Hystrix系列-3-Hystrix的配置-通过代码构造配置
- DHCP配置
- 在一个千万级的数据库查寻中,如何提高查询效率
- 直线距离