Android:dagger扩展库
概述
之前我们使用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 { @Subcomponent.Builder public abstract class Builder extends AndroidInjector.Builder { } }
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 bind(CoffeeReceiverSubcomponent.Builder builder); }
5.将创建的Module注入到ApplicationComponent中,即把其添加至ApplicationComponent的modules属性列表
@Component(modules = {AndroidInjectionModule.class, AndroidSupportInjectionModule.class, CoffeeModule.class, ...}) public interface TodoComponent extends AndroidInjector { @Component.Builder abstract class Builder extends AndroidInjector.Builder { } }
6.创建自定义Application,继承了DaggerApplication,因为dagger把该添加的DispatchingAndroidInjector添加进去了。但是,并没有实现v4包的HasSupportFragmentInjector,这里需要手动添加进去。
public class TodoApplication extends DaggerApplication implements HasSupportFragmentInjector{ @Inject DispatchingAndroidInjector fragmentSupportInjector; public void onCreate() { super.onCreate(); } @Override protected AndroidInjector applicationInjector() { return DaggerTodoComponent.builder().create(this); } @Override public AndroidInjector 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 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 { 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学习后多加练习细细体会
推荐阅读
-
Android实现扩展Menu的方法
-
Android中Glide库的使用小技巧总结
-
Android添加glide库报错Error: Failed to resolve: com.android.support:support-annotations:26.0.2的解决
-
android编程实现图片库的封装方法
-
如何用C代码给Python写扩展库(Cython)
-
thinkphp框架类库扩展操作示例
-
android 数据库操作(常见的数据库管理系统)
-
Android编程之SQLite数据库操作方法详解
-
Android EasyPermissions官方库高效处理权限相关教程
-
Android数据持久化之SQLite数据库用法分析