Dagger2的使用

本篇的内容不涉及Dagger2的源码,只是为了更好的使用.

想进一步了解的话可以阅读以下文章:
dagger2让你爱不释手-基础依赖注入框架篇
dagger2让你爱不释手-重点概念讲解、融合篇
dagger2让你爱不释手-终结篇

Dagger2 这次入门就不用放弃了
Dagger2 使用正确姿势
Dagger2 彻底了解如何构建依赖关系

本着不重复造轮子的精神,理论上面几篇文章很详细了,那我就直接结合我的开发来谈谈吧

Dagger2的配置

目录添加apt支持,apt是用于自动生成代码来进行依赖注入的。
项目中的build.gradle添加:

dependencies {
        //构建android项目的gradle
        classpath 'com.android.tools.build:gradle:2.2.3'
        //构建dragger2
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }

在module的build.gradle添加:

apply plugin: 'com.neenbedankt.android-apt'

    android{
        ...
    }

dependencies {
    provided 'org.glassfish:javax.annotation:10.0-b28'
    compile 'com.google.dagger:dagger:2.0.2'
    compile 'com.google.dagger:dagger-compiler:2.0.2'
}

第一步:编写Module

编写ActivityModule

@Module
public class ActivityModule {
    private Activity mActivity;

    public ActivityModule(Activity activity) {
        mActivity = activity;
    }

    @Provides
    @ActivityScope
    public Activity provideActivity() {
        return mActivity;
    }

    @Provides
    @ActivityScope
    public List<DataListBean> provideList() {
        return new ArrayList<>();
    }
    @Provides
    @ActivityScope
    public PlanManagerAdapter provideAdapter(List<DataListBean> data) {
        return new PlanManagerAdapter(data);
    }
}
  • 类要用@Module注解来标示,可以看到我这个AcitivtyModule中定义了一个构造函数,需要传进来一个XXXActivity对象。

  • 我们需要明确Module的作用是用来提供生成依赖对象的,比如我要注入PlanManagerAdapter,那么这个Module的作用就是需要生成一个PlanManagerAdapter 的对象,来让Dagger2注入到XXXActivity中。当然还可以是XXXPresenter对象,或者普通的bean对象等.

  • 细心的同学应该看到了函数provideAdapter上面使用@Provides注解(@ActivityScope后面讲),用@Provides注解的函数名需要以provide开头,然后后面接什么内容都可以,看自己喜欢,事实上这里是根据返回值类型来标识的,方法名并不重要,只需要保证以provide开头即可。

  • 然后这里需要传入一个List<DataListBean>参数,仔细看我上面的代码中还定义了两个函数,分别为provideList和provideActivity,这里provideAdapter的参数就是通过provideList这两个函数来获取的。剩下的provideActivity则是会出现在开发中的需要activity的地方,用@Inject注解标识就可以获取到activity的对象,如果没有声明provideList这个函数的话,编译期间会报错。

编写AppModule

我的项目中提供一个全局的RetrofitHelper对象来进行网络请求,他的生命周期是和APP一致的,这个时候我们就需要编写AppModule 了。

@Module
public class AppModule {
    @Provides
    @Singleton
    RetrofitHelper provideRetrofitHelper() {
        return new RetrofitHelper();
    }
}
  • 这里provide方法除了@Provides之外还添加了一个@Singleton注解,这里只是标注一下让大家看起来方便识别是全局单例的对象只是添加一个@Singleton注解并不能说明RetrofitHelper对象就是单例,这还要看在哪里初始化(后面讲)。

第二步:编写Component

编写ActivityComponent

@ActivityScope
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
    void inject(HomeActivity homeActivity);
}

编写AppComponent了:

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    RetrofitHelper retrofitHelper();  //http的帮助类
}
  • 我们编写的ActivityComponent需要用@Component注解来标识,同时声明了(modules = ActivityModule.class),并且依赖了AppComponent(dependencies = AppComponent.class),Component之间也可以依赖,然后提供了一个方法,叫做inject,用来在Activity中注入。这里的AppComponent提供了一个方法,用来暴露RetrofitHelper对象的。

第三步:在目标类中(activity)注入

Make Project,之后就会生成DaggerActivityComponent和DaggerAppComponent的类,之后我们在MyApplicaiotn中实例化DaggerAppComponent:

private static AppComponent appComponent;
 @Override
    public void onCreate() {
        super.onCreate();
        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule())
                .build();
    }
 //初始化AppComponent
    public static AppComponent getAppComponent() {
        return appComponent;
    }

然后在Activity的onCreated函数中编写如下代码:

DaggerActivityComponent.builder()
.appComponent(MyApplication.getAppComponent())
.activityModule(new ActivityModule(this))
.build()
.inject(this);

这些工作做完之后接下来看下调用代码

  • 首先在activity中注入PlanManagerAdapter 对象

这个对象就是来自ActivityModule中的provideAdapter方法返回的对象,此处再次强调因为PlanManagerAdapter构造需要传入参数,这个参数也要在ActivityModule中创建对象并返回.

  • 其次就是在Presenter中注入了activity(可以作为上下文)和网络请求帮助类RetrofitHelper


  • 大家会有疑问RetrofitHelper并没有在ActivityModule中啊,但是大家不要忘了,我在ActivityComponent中进行了依赖,这样就可以解决问题了


注入方式

  • 注入实例的方式一种是通过编写Moudle,并且提供一些provideXXX()的方法,然后通过Component把这些对象进行注入。
  • 其实在Dagger2中还有一种方式实现对象的注入,这种方式比较简单。就像上面我需要在activity中注入PlanManagerAdapter对象,除了编写Moudle,我们还可以在PlanManagerAdapter的构造函数中添加@Inject注解即可,代码如下:



    这样就不需要在Moudle中添加provideXXX()的方法了,两种方式都可以.
    当在目标类(activity)遇到

@Inject
类XXX  XXX;

整个Dagger2的依赖注入的过程如下:

步骤1:查找Module中是否存在创建该类ProvidesXXX的方法。
步骤2:若存在创建类ProvidesXXX方法,查看该方法是否存在参数
    步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数(上面讲过有参数的情况)
    步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,看构造函数是否存在参数
    步骤3.1:若存在参数,则从步骤1开始依次初始化每个参数
    步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束

为什么ActivityComponent要提供一个inject方法

在XXXActivity中对对某些需要注入的成员添加@Inject注解的时候,Dagger2就会生成一个XXXActivity_MembersInjector的东西,这个是对成员变量进行注入的关键类,涉及到再深入的内容,我就没再研究了。我们只需要知道当我们需要向目标类(Activity)注入一些成员变量的时候,我们需要在ActivityComponent中提供一个方法:

void inject(XXXActivity xxxActivity);

并且在初始化的时候调用这个方法,才能成功注入。

Scope的使用,如何实现单例?

在我们的AppComponent中添加了一个注解为@Singleton
,@Singleton就是一个Scope,事实上@Sinleton中并没有创建单例的能力,那么AppComponent中提供的依赖注入是如何实现单例的呢。其实这个原理很简单。首先Module提供了创建实例的方法,接着AppComponent
中对Module进行管理,最后MyAppComponent在自定义Applicaiton中被实例化了一次。

其实@Singletop还有有一些作用的,首先一方面能让你直面的了解到这是一个单例,其次这个@Singletop能够更好的管理Modlue和Component之间的关系。
Dagger2需要保证Component和Module是匹配的,就需要用到这个注解。
为什么这样说,上文中我定义了一个ActivityScope

@Scope
public @interface ActivityScope {
}

因为是因为我在AppComponent中是有@Singletop,ActivityComponent中依赖了AppComponent
,所以我们需要使用一个Scope来匹配他们之间的关系,不然就会在编译期间报错。并不是说ActivityScope能让实例和Activity生命周期一致。和Activity生命周期一致是因为ActivityComponent是在Activity中生成实例的。

Qualifier 限定符的作用以及使用。

这也是一个很强大的注解,首先为什么需要用这么一个东西呢,之前说道过,在Module中的provide方法实际上是根据返回值来进行识别的。但是假设我需要根据不同的需求传入不同的构造参数的时候,如何区分呢?比如:一个Presenter,可能他有两个构造函数,分别对应不同的需求,这种情况下,provide方法的返回值都是Presenter,那么就需要使用Qualifier。具体怎么使用呢。

首先声明一个注解用@Qualifier修饰,然后在需要区别的地方添加就行了,下面是一个实例代码:

深入理解Java:注解(Annotation)自定义注解入门

@Module
public class AppModule {
private final App app;

public AppModule(App app) {
    this.app = app;
}

@Provides
@Singleton
@ForApplication
Context provideAppContext() {
    return app;
}

@Provides
@Singleton
Prefser providePrefser(@ForApplication Context context) {
    return new Prefser(context);
}

@Provides
@Singleton
AccountManager provideAccountManager(@ForApplication Context context) {
    return AccountManager.get(context);
}

首先在provide中添加一个注解@ForApplicition,接着在需要使用这个Context的地方再次标示即可。这样假设有其他一些提供了Activity的Context的地方和这里发生冲突的时候,Dagger2也能准确找到这个Applicaiton的Context。

总结

写完才发现,虽然对Dagger的使用心里很明白了但是写成文字叫大家理解还是火候不够,还有疑问的可以参考下开篇的文章或者留言一起交流。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • 这篇文章是对Dagger2使用的一个总结,参考了许多内容,会在下面把参考的资料列出来 什么是Dagger2 1.D...
    石器时代小古董阅读 1,240评论 4 9
  • 引入Dagger2 首先,我们需要将Dagger2的依赖写入我们的gradle中,具体配置如下 配置好之后就可以使...
    vonnie阅读 616评论 0 0
  • 本文的分析基于dagger2的2.7版本。 谷歌开发维护的Dagger2出来有很长时间了,目前在很多开源项目上也能...
    sososeen09阅读 13,580评论 31 108
  • 简介 dagger2目前由谷歌进行维护的一个注入式框架,优点在于组件之间的解耦,有助于程序的扩展性。 使用步骤 配...
    Goorwl阅读 223评论 0 0
  • 七里香堤业主群 维权榜上尔为尊 峥嵘岁月不辞苦 正气一身万古存 中华新韵
    阆苑寒梅阅读 271评论 4 7