Dagger2使用指南

什么是Dagger2?

Dagger2是一个依赖注入框架,那么何为依赖注入呢?依赖注入是面向对象编程的一种设计模式,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。
很多人说Dagger是脱裤子放屁,实际上是他们对Dagger的作用产生了误解,Dagger的作用是管理对象之间的依赖关系,从而降低耦合,而不是为了构建一个对象,是否使用Dagger的一个标准是看两个类之间的关系是依赖关系,还是组合或者聚合的关系。
举个例子说明,一个类Person,另一个类Car,如果Person的某个方法比如说drive,需要引用Car,则称Person类依赖于 Car类

Public Person{

...
public void drive(){
  Car toyota=new Car("TOYOTA");
  toyota.挂档;
  toyota.踩油门;
  toyota.打方向;
}
}

这其中的依赖关系,就导致了Person对象需要负责对象toyota的创建,甚至是整个生命周期的管理,而这样显然会带来耦合度高,不易维护等缺点,比如说要让这个男孩驾驶一辆Audi,则还需要修改类Person的代码。所以我们通常从外部传入一个Car对象,这就是所谓的依赖注入

Public Person{
...
 Car toyota;
public Person(Car car){
toyota=car;
}

public void drive(){
  toyota.挂档;
  toyota.踩油门;
  toyota.打方向;
}
}

但是直接在构造方法里面传递对象又会造成一个问题,随着后续业务增加也许又需要传入Phone,Computer试想一下如果一个工程中有5个文件使用了Person那是不是要改5个文件。
所以有的时候我们会直接通过set方法来注入对象,这就需要我们每次使用时都要做null判断,因为你可能会忘记为它set值,有没有更优美的解决方法呢?Dagger2来了。
dagger2的github地址:
https://github.com/google/dagger

使用步骤

1.添加依赖

  implementation 'com.google.dagger:dagger:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'

People.java

public class People {

    public People () {
        System.out.println("a people created");
    }

    public  void print(){
        Log.d("sun"," i am people");
    }
}

2.创建Module
什么是Module,你可以把它想象成一个工厂,可以向外提供一些类的对象,类名用@Module标注,方法用@Provides标注,类名和方法名没有特别规范
MainModule .java

@Module
public class MainModule {

    @Provides
    People providesPerson() {
        return new People ();
    }
}

3.创建MainComponent
MainComponent.java

@Component(modules = {MainModule.class})
public interface MainComponent {

    void inject(MainActivity mainActivity);
}

4.重新Build项目
5.在MainActivity中将component 关联进去

public class MainActivity extends AppCompatActivity {
@Inject
People people;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MainComponent mainComponent =DaggerMainComponent.builder().mainModule(new MainModule()).build();
        mainComponent.inject(this);
        people.print();
    }
}

假定一个场景,现在People的构造方法改变了,我们给它增加了一个name属性和一个context属性

public class People {
    Context context;
    String name;
    public People(Context context,String name) {
        System.out.println("a people created");
        this.name=name;
        this.context=context;
    }

    public void print(){
        Log.d("sun"," i am people"+name);
        Toast.makeText(context,"i am people"+name,Toast.LENGTH_LONG).show();
    }
}

相应的修改MainModule.java

@Module
public class MainModule {

    public MainModule() {
    }
    @Provides
    People providesPerson(Context context,String log){
        return new People(context,log);
    }
}

或者新建一个Moudle

@Module
public class SubMainModule {

    @Provides
    People providesPerson(Context context, String log){
        return new People(context,log);
    }
}

新建ContextComponent和ContextModule

@Module
public class ContextModule {
    Context context;

    public ContextModule(Context context) {
        this.context = context;
    }
    @Provides
    Context getContext(){
        return context;
    }
}

@Component(modules = {ContextModule.class})
public interface ContextComponent {
    Context getContext();
}

同理创建StringComponent和StringModule。

然后修改MainComponent ,添加Component之间的依赖

@Component(dependencies = {StringComponent.class,ContextComponent.class},modules = {MainModule.class})
public interface MainComponent {
    void inject(MainActivity mainActivity);

}

最后绑定Activity

StringComponent stringComponent=DaggerStringComponent.builder().stringModule(new StringModule("abc")).build();
ContextComponent contextComponent=DaggerContextComponent.builder().contextModule(new ContextModule(mainActivity)).build();
DaggerMainComponent.builder().mainModule(new MainModule()).stringComponent(stringComponent).contextComponent(contextComponent).build().inject(mainActivity);

@Qualifier

如果一个Moudle提供了多种创建对象的方式,可以通过自定义标签的方式指定使用哪种方式

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PeopleWithContext {
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PeopleWithName {
}

在Moudler中分别注解提供对象的方法

  // ...
    @PersonWithContext
    @Provides
    public Person providesPersonWithContext(Context context) {
        return new Person(context);
    }

    @PersonWithName
    @Provides
    public Person providesPersonWithName() {
        return new Person("yxm");
    }

在依赖注入的地方也使用标签注解

  @PersonWithContext
    @Inject
    Person p1;

    @PersonWithContext
    @Inject
    Person p2;

@Scope

@Scope可用于修饰自定义的注解,用@Scope修饰的注解来修饰
Moudle里面提供对象的方法会产生单例效果,但是注意必须给相应的Component提供注解,而且如果Moudle里面有多个提供对象的方法,那么每一个方法都会产生一个对象,实际上不是单例,@Singleton就是用@Scope修饰的注解

@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
    @ActivityScope
    @Provides
    Person providesPeople {
        return new Person();
    }
@ActivityScope
@Component(modules = {ActivityModule.class})
public interface ActivityComponent {
    void inject(MainActivity mainActivity);
}

总结:

Dagger说白了给我们提供了灵活创建对象的方式,对象的创建是在一层一层的依赖中实现的,例如前面的例子,修改构造函数时,只需要修改相应的Moudle,并且在当前Moudle中提供创建对象的元素,或者重新创建新的Moudle和Component,然后添加Component依赖,然后修改绑定的元素的代码,乍一看,这岂不是更复杂,实际上,有一些被依赖的Component对象并不是在需要使用时就创建的,而是提前创建或者封装在一些工具类中,从而简化我们的代码

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

推荐阅读更多精彩内容

  • 原文地址Dagger2 入门,以初学者角度 依赖注入 Dagger2是Android中比较热门的依赖注入框架,什么...
    Marlon_IT阅读 1,275评论 1 16
  • 什么的依赖注入 在软件工程中,依赖注入是实现控制反转的方式之一。百度百科中对于控制反转的解释如下:控制反转(Inv...
    小甜李子阅读 1,677评论 5 3
  • 最近在项目中使用了 Dagger2 这个依赖注入的框架,在这里记录一下。第一次写技术文章,不足之处请多指教。不过真...
    lshilll阅读 1,467评论 0 0
  • 一、首先你要知道什么是依赖? 想要理解Dagger2,首先你要理解一个概念,就是什么是依赖,懂的同学可以省过此段。...
    为梦想战斗阅读 442评论 0 0
  • 光阴荏苒,岁月如梭。 三十年岁月匆匆而过,我们却已经物是人非。但年少时无数的往事,却依然犹如昨日,历历在目。 那是...
    初三四班某学生阅读 517评论 0 0