1、依赖的注入和配置独立于组件之外,注入的对象在一个独立、不耦合的地方初始化,这样在改变注入对象时,我们只需要修改对象的实现方法,而不用大改代码库。

2、依赖可以注入到一个组件中:我们可以注入这些依赖的模拟实现,这样使得测试更加简单。

3、app中的组件不需要知道有关实例创建和生命周期的任何事情,这些由我们的依赖注入框架管理的。

我觉得,dagger2这样的依赖注入框架对MVP架构来说,是最好的解耦工具,可以进一步降低modle-view-presenter之间的耦合度。
所以,如果你的项目在使用MVP架构开发,强烈建议配合dagger2一起使用。

接下来,在贴代码之前,我先说说明下我的MVP架构和传统的MVP有些不同,传统MVP的M层处理业务逻辑,P层仅仅是V和M的桥梁;而我的P层同时处理与model相关的业务逻辑,不处理View层次的逻辑,View层次的逻辑交给V自己处理,M层仅仅是bean,这种方式是根据开发中的实际情况而作的考虑,这里先不作讨论。

先看结构图:

接下来,分解这张图:
AppComponent: 生命周期跟Application一样的组件。可注入到自定义的Application类中,@Singletion代表各个注入对象为单例。

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {Context context();  // 提供Applicaiton的ContextThreadExecutor threadExecutor();   // 线程池ApiService apiService();  // 所有Api请求的管理类SpfManager spfManager();  // SharedPreference管理类DBManager dbManager();  // 数据库管理类
}

AppModule: 这里提供了AppComponent里的需要注入的对象。

@Module
public class AppModule {private final MyApplication application;public AppModule(MyApplication application) {this.application = application;}@Provides@SingletonContext provideApplicationContext() { return application;}@Provides@SingletonThreadExecutor provideThreadExecutor(JobExecutor jobExecutor) {return jobExecutor;}@Provides@SingletonApiService providesApiService(RetrofitManager retrofitManager) {return retrofitManager.getService();}@Provides@SingletonSpfManager provideSpfManager() {return new SpfManager(application);}@Provides@SingletonDBManager provideDBManager() {return new DBManager(application);}
}

这里细心的童鞋可能发现,为何有些方法直接返回入参,有些需要返回一个new的对象呢?
这里如果对DBManager的写法换成:

DBManager provideDBManager(DBManager dbManager) {return dbManager;
}

这样编译不会通过,会报一个循环依赖的错误,这种写法需要在返回参数和入参不是同一个类的情况下才可以。感兴趣的可以查看dagger2生成的代码。

对于直接返回的类JobExecutor、RetrofitManager,它们类的构造函数一定要加上@Inject的注解:

@Inject
public JobExecutor() {// 初始化// ......
}

接下来谈谈ActivityComponent,可以看到有个@ActivityScope注解,这个注解是自定义的,对应Activity的生命周期,Dagger2可以通过自定义注解限定注解作用域,一般在Module里规定scope的生命周期,比如下面的ActivityScope在ActivityModule里绑定。

@Scope
@Retention(RUNTIME)
public @interface ActivityScope {}

ActivityComponent:生命周期跟Activity一样的组件,这里提供了inject方法将Activity注入到ActivityComponent中,通过该方法,将Activity中需要注入的对象注入到该Activity中。

@ActivityScope
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {Activity activity();void inject(LoginActivity loginActivity);void inject(MainActivity mainActivity);// ....
}

ActivityModule:注入Activity,同时规定Activity所对应的域是@ActivityScope

@Module
public class ActivityModule {private final Activity activity;public ActivityModule(Activity activity) {this.activity = activity;}@Provides@ActivityScopeActivity activity() {return this.activity;}
}

至此,注入工作初步完毕了,看到这里,可能有童鞋有疑问,Presenter(或者Biz)的注入在哪里,为何没在ActivityComponent里?
是的,正常来说,结构图应该是下面这张图的样子:

我建议使用这种方式,对于不同的Activity,创建各个对应的ActivityCompontent,同时把Presenter(Biz)注入到Component的视图中,这也是dagger2推荐的做法,Dagger 2希望使用@Component注解接口将依赖关系链接起来。

而我的做法没有把Presenter注入到ActivityComponent中,因为Presenter的作用域和Activity一样,好处是节省代码(- -),大家可以自行选择注入方式。

使用:

public class LoginActivity extends BaseActivity implements LoginView, ValidCodeView {@Inject LoginPresenter loginPresenter;@Inject ValidCodePresenter validCodePresenter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);initInject();// 此处省略N行代码}private void initInject() {// 构建Component并注入getActivityComponent().inject(this);loginPresenter.attachView(this);validCodePresenter.attachView(this);}//  建议写在基类Activity里protect ActivityComponent getActivityComponent(){return  DaggerActivityComponent.builder().appComponent(getAppComponent()).activityModule(getActivityModule()).build();}//  建议写在基类Activity里protect ActivityModule getActivityModule(){return new ActivityModule(this);}// 建议写在MyApplication类里public AppComponent getAppComponent(){return DaggerAppComponent.builder().appModule(new AppModule((MyApplication)getApplicationContext())).build();}
}

其中LoginPresenter:

@ActivityScope
public class LoginPresenter extends DefaultMvpPresenter<LoginView, RESTResult<UserVO>> {// 此处省略@Injectpublic LoginPresenter(ApiService apiService, ThreadExecutor jobExecutor, SpfManager spfManager) {this.apiService = apiService;this.jobExecutor = jobExecutor;this.spfManager = spfManager;}public void login(String mobile, String code) {// todo}
}

这样,dagger2的简单使用就介绍完毕了,如果有对一些基础概念不是很理解的童鞋,可以查看官方文档。

文/YoKey(简书作者)
原文链接:http://www.jianshu.com/p/c2feb21064bb
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

Android 之dragger使用相关推荐

  1. Android内存泄露抓取工具leakcanary

    引言 "A small leak will sink a great ship." - Benjamin Franklin 概述 某些对象的生命周期有限,当它们的工作完成以后,将会 ...

  2. android控件名,介绍一个名为Dragger的android控件

    前言 最近在做一个项目的时候要求使用一个弹出的效果,正好遇见如下的一个效果, 感觉效果很好看就用了 项目地址如下:Dragger 开始使用:(开发环境为Android Studio) 在你的build ...

  3. Dragger.android的使用

    Dagger2特别提供了一个针对 Android 使用的简化流程. 1.给你的Activity 写一个 Subcomponent,应引用所需的 Module @Subcomponent(modules ...

  4. Android学习系列(10)--App列表之拖拽ListView(上)

    研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨.       鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. ...

  5. Android开发常用的插件及工具

    1.GitHub,这个不管是做安卓还是其他,只要是开发就必上的网站,也是天朝没有墙掉为数不多的网站 2.Stack OverFlow,这个和上面一样,国外非常著名的问答网站,在上面基本上很多问题都可以 ...

  6. android各组件翻译,Android App框架指南(译文)

    该系列文章是对Android推出的架构组件相关文章,按作者自己理解来翻译的,同时标记有作者自己一些简单笔记.如果读者发现文中有翻译不准确的地方,或者理解错误的地方,请不吝指教. 源自Android官方 ...

  7. android ListView和GridView拖拽移位具体实现及拓展

    关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:              首 ...

  8. Android自定义processor实现bindView功能

    一.简介 在现阶段的Android开发中,注解越来越流行起来,比如ButterKnife,Retrofit,Dragger,EventBus等等都选择使用注解来配置.按照处理时期,注解又分为两种类型, ...

  9. Android常用热门开源库汇总(持续更新)

    原文转载:https://www.yundashi168.com/344.html 请及时关注原文网站,因为后续持续更新都在原网站更新.请多多点赞和关注. 前言 收集了一些比较常见的开源库,特此记录( ...

最新文章

  1. 如何使用C++ Builder 6.0连接Access数据库
  2. treeview递归绑定的两种方法
  3. Nginx面试!mysql时间类型以及获取当前时间,干货满满
  4. CouncurrentHashMap源码解析
  5. Php无刷新修改url,history 实现无刷新更改url和页面内容
  6. 【干货】掌握这5招,Linux排障不再怕
  7. Android无需权限显示悬浮窗, 兼谈逆向分析app
  8. Delphi文件操作函数
  9. 晶振选型时的问题库(z)
  10. JavaWeb:XML总结
  11. 53 - 9. 回文数
  12. filter过滤器_不了解布隆过滤器?一文给你整的明明白白
  13. TensorFlow tf.keras.callbacks.CSVLogger
  14. Kotlin入门(11)江湖绝技之特殊函数
  15. Android是如何绘制View的
  16. rootkit后门检测工具rkhunter
  17. 子列和列_最大连续子列和问题 JAVA实现
  18. 为什么阿里会选择 Flink 作为新一代流式计算引擎?
  19. 来自朋友圈的“精神食粮”
  20. 基于Edge浏览器的沙拉划词插件使用教程(好用的翻译插件)

热门文章

  1. 【redis】redis之持久化机制
  2. centos7下操作7z文件
  3. 模块DIY——基于DDS直接数字频率合成技术自制的可编程任意波形发生器模块(DDS原理、寄存器解读、原理图设计、驱动程序-适用于AD9833/AD9834/AD9838)
  4. Python仓库管理系统源代码,库存管理系统源码,基于flask,内含数据库文件,已实现出入库、库存预警,库存搜索等功能
  5. 【web前端特效源码】使用HTML5+CSS3制作一个会动的音频loading加载动画效果~~适合初学者~超简单~ |前端开发|IT编程
  6. BIM二级考试第17期第一题用revit2016系统库中现场浇筑楼梯平台的bug
  7. JavaFx_JDK1.8 简单操作
  8. mtr命令行工具的理解和应用总结
  9. 从奥本海默的浮沉谈科学与政治的关系
  10. 和大华电子称进行对数据通讯