概述
之前我们使用dagger注入时,都需要activity、fragment等宿主在component中注册,比如:
((SomeApplicationBaseType) getContext().getApplicationContext())
.getApplicationComponent()
.activity(this)
.build()
.inject(this);
这样之后才可以使用该component中的依赖实例(也可以是父组件中能拿到的),随着开发的深入,这类代码越来越多,很不利于重构,同时也打破了依赖注入的核心原则:一个类不应该知道如何注入它。
Dagger.Android库是Dagger库的补充,dagger.android中的类提供了一种简化此模式的方法,从而在一定程度上避免了上述问题的发生。
使用流程
1.在ApplicationComponent中注入AndroidInjectionModule,如果项目中用到v4包的Fragment,还需注入AndroidSupportInjectionModule.建议把两个Module都注入ApplicationComponent中:
@Component(modules = {AndroidInjectionModule.class, AndroidSupportInjectionModule,...})
public interface ApplicationComponent {
void inject(MyApplication application);
}
2.创建Android库的核心类(Activity、Fragment、Service、IntentService、BroadcasReceiver),需要注意的就是:AndroidInjection.inject(T)方法的调用位置
- 在Activity、Service及IntentService的onCreate()中,super.onCreate()方法以前。
- 在Fragment中onAttach()中,super.onAttach()方法以前。如果是v4包的Fragment,应调用AndroidSupportInjection.inject()方法。
- 在BroadcastReceiver的onReceive()中,super.onReceive之前调用。
3.创建子组件 - @Subcomponent,其继承自AndroidInjector,而T就是step2创建的Android库的类型
@Subcomponent
public interface CoffeeReceiverSubcomponent extends AndroidInjector<CoffeeReceiver> {
@Subcomponent.Builder
public abstract class Builder extends AndroidInjector.Builder<CoffeeReceiver> {
}
}
4.创建Module,其subcomponents属性值就是3创建的子组件。在其内必须声明一个抽象方法,该抽象方法返回AndroidInjector.Factory<?>实例,而其参数为3创建的XxSubcomponent.Builder实例。
@Module(subcomponents = CoffeeReceiverSubcomponent.class)
public abstract class CoffeeModule {
@Binds
@IntoMap
@BroadcastReceiverKey(CoffeeReceiver.class)
abstract AndroidInjector.Factory<? extends BroadcastReceiver> bind(CoffeeReceiverSubcomponent.Builder builder);
}
5.将创建的Module注入到ApplicationComponent中,即把其添加至ApplicationComponent的modules属性列表
@Component(modules = {AndroidInjectionModule.class, AndroidSupportInjectionModule.class, CoffeeModule.class, ...})
public interface TodoComponent extends AndroidInjector<TodoApplication> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<TodoApplication> {
}
}
6.创建自定义Application,继承了DaggerApplication,因为dagger把该添加的DispatchingAndroidInjector添加进去了。但是,并没有实现v4包的HasSupportFragmentInjector,这里需要手动添加进去。
public class TodoApplication extends DaggerApplication implements HasSupportFragmentInjector{
@Inject
DispatchingAndroidInjector<Fragment> fragmentSupportInjector;
public void onCreate() {
super.onCreate();
}
@Override
protected AndroidInjector<TodoApplication> applicationInjector() {
return DaggerTodoComponent.builder().create(this);
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return fragmentSupportInjector;
}
}
注意:只有当BroadcastReceiver在AndroidManifest.xml中注册时,才能使用DaggerBroadcastReceiver。 当在动态注册BroadcastReceiver时,推荐使用构造函数注入。
官方demo使用方式
官方demo中的使用方式简洁方便,主要是使用了一个注解—@ContributesAndroidInjector
@Target(METHOD)
public @interface ContributesAndroidInjector {
// 要注入到生成的dagger.Subcomponent中的Module。
Class<?>[] modules() default {};
}
官方文档对它是这么解释的:为其注解的方法生成相应的AndroidInjector。该注射器是 dagger.Subcomponent的实现
- 此注释必须应用于返回具体的Android框架类型(例如:FooActivity、BarFragment、MyService等)的Module中的抽象方法。
- 该方法应该没有参数。
具体可看官方例子mvp-dagger
1.自定义一个application,继承DaggerApplication:
public class ToDoApplication extends DaggerApplication {
@Inject
TasksRepository tasksRepository; // component中暴露出来
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder().application(this).build();
}
}
2.创建一个管理全局的component:
@Singleton
@Component(modules = {TasksRepositoryModule.class,
ApplicationModule.class,
ActivityBindingModule.class,
AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<ToDoApplication> {
TasksRepository getTasksRepository();
// Gives us syntactic sugar. we can then do DaggerAppComponent.builder().application(this).build().inject(this);
// never having to instantiate any modules or say which module we are passing the application to.
// Application will just be provided into our app graph now.
@Component.Builder
interface Builder {
@BindsInstance
AppComponent.Builder application(Application application);
AppComponent build();
}
}
3.创建一个ActivityBindingModule用于管理所有应用内的activity(子组件)
@Module
public abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector(modules = TasksModule.class)
abstract TasksActivity tasksActivity();
@ActivityScoped
@ContributesAndroidInjector(modules = AddEditTaskModule.class)
abstract AddEditTaskActivity addEditTaskActivity();
@ActivityScoped
@ContributesAndroidInjector(modules = StatisticsModule.class)
abstract StatisticsActivity statisticsActivity();
@ActivityScoped
@ContributesAndroidInjector(modules = TaskDetailPresenterModule.class)
abstract TaskDetailActivity taskDetailActivity();
}
4.每个activity都可以再通过module属性继续提供依赖或子组件
@Module
public abstract class TasksModule {
@FragmentScoped
@ContributesAndroidInjector
abstract TasksFragment tasksFragment();
@ActivityScoped
@Binds abstract TasksContract.Presenter taskPresenter(TasksPresenter presenter);
}
如上的tasksFragment()中 @ContributesAndroidInjector也可以有module继续依赖下去
TasksRepositoryModule可以当做一个全局的数据module,ApplicationModule可以提供一些全局实例,如网球请求的client等等,AndroidSupportInjectionModule则是使用v4包时需要注入的。
总结
扩展库可以使dagger的使用更为简单方便,具体的需要查看官方demo学习后多加练习细细体会