dagger2的使用和优缺点分析

前言

最近在做技术通道代码评审时,发现腾讯挺多项目有使用比较“老”的dagger2框架,自己也是几年前在上家公司使用过,具体使用和原理都有点模糊了,完全不好评判评审代码优劣。 但是明确记得jectpack的hilt 是基于dagger2优化的。也私聊了部分开发同学,为什么不使用更好用的hilt,得到的答复基本都是历史代码为了统一代码风格。在review代码时候发现依赖注入看起来比较乱,并没有看出啥独到之处。为了更好的评审代码,抽空补补dagger2发现这个框架还是挺有意义的。

下面分3个部分介绍dagger2, 分别介绍他的基本使用和框架实现原理以及熟悉dagger2框架实现意义以及自己在学习该框架的一些思考总结

1.基本的使用

dagger2出现的背景:
比如项目中有一个全局到处都用到的对象,以我们项目举例股票对象:Stock 假如我要改动Stock对象的默认无参构造为每个地方都要给他传一个参数进去 而这个Stock对象在整个项目成百上千个地方都直接new Stock(),有这种改动时 需要全部替换为new Stock("参数")。当然我们可以全局搜索替换。不纠结这个 想表达的就是创建对象在各个地方都是new的,耦合比较严重,dagger2就是为了解决这种耦合,把new的过程通过APT在编译阶段生成代码,我们只需要通过注解标识,自动帮我们new出来,这样我们不用去改成百上千的地方,只需要改一个地方就行

上面的背景介绍完,你可能会想到这和网络请求封装中间层一样吗?到处都直接使用volley网络框架,后面要升级到okhttp每个地方都要替换,如果有个中间层,直接替换中间层的实现就好一样样的。
1.1 引入依赖:
implementation 'com.google.dagger:dagger:2.4'
annotationProcessor 'com.google.dagger:dagger-compiler:2.4'

dagger2的使用主要涉及4个对象:对象、module、 component、inject

1.2 对象定义:

对象就一个简单的股票对象就行:

public class StockObject {}
1.3 封装module:

使用module和Provides注解,提供对象时创建股票对象:

@Module
public class StockModule {

    @Provides
    public StockObject providerStockObject(){
        return new StockObject();
    }
}

1.4 定义component:

组件使用接口,通过component注解指定module:

@Component(modules = {StockModule.class, BrokersModule.class})
public interface TestComponent {

    void injectMainActivity2(MainActivity2 activity2);
}
1.5 调用注入代码:

使用注入的注解来标识要注入的对象,然后编译后的component调用注入方法,这个时候对象已经被创建了:

  @Inject
  StockObject stock;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        // 方式一
        DaggerTestComponent.create().injectMainActivity2(this);
        Log.i("测试", stock.hashCode() + " MainActivity2");
    }

2.实现原理

从上面几个步骤的使用可以看出主要使用了APT技术,通过不同的注解,在编译时生成一些辅类,从1.1的注解处理工具也可以看出实现原理
我们可以看下编译后生成的类如下:


image.png
2.1源码查看入口
DaggerTestComponent.create().injectMainActivity2(this);

我们代码里直接在activity调用生成的component的注入方法,有个共性提前说下,生成的代码大部分都提供了create方法,里面其实就创建了生成类对象。
直接上图,关键流程步骤都标注好了,


image.png

走到上面第9步,再看下provider的get方法,实现在生成的Factory里面,删除无用代码,主要调用 module.providerStockObject() 这个就是我们自己写的module中创建的真实的对象:

public final class StockModule_ProviderStockObjectFactory implements Factory<StockObject> {
  private final StockModule module;

  @Override
  public StockObject get() {
    return Preconditions.checkNotNull(
        module.providerStockObject(), "Cannot return null from a non-@Nullable @Provides method");
  }
}

上面就是整个注入的源码实现,还是比较清晰的
1.在初始化时,生成组件内部通过建造者模式创建了module对象,调用工厂类传入module生成provider,再把provider给到注入器
2.在使用页面调用生成组件注入当前activity
3.调用注入器的注入成员方法,获取当前activity的注入成员,使用provider的get赋值
4.在provider中,直接获取module的具体提供对象,也就是真实的对象

3.意义和思考(总结)

有意义的地方是:
1.可以拓展自己的技术面,不然看不懂别人的代码无法装逼
2.dagger的设计初衷是解耦合,但是实际使用比较比较难用。如果只是为了不改多个地方实际可以做一个封装,类似他源码实现用工厂模式、中间层 代理等方式来简化。
3.里面比较亮点的地方反而是他的注解处理实现,开发者只需要关注注解使用。和Arouter比较类似,主要目的是简化开发使用,通过APT生成一些帮助类,业务开发不需要关注具体实现,来实现解耦的目的。在架构和封装角度看 还是值得学习的。

总结:
dagger2框架主要是通过注解方式实现依赖注入,调用地方不用自己new 对象,通过APT在编译时候生成代码实现帮助new对象功能,实现解耦。里面涉及基本的对象、module、component、注入四个大的???。module里面封装真实的对象,然后给到组件,组件根据谁注入的帮调用注入的传递基本的对象。类比在家下单点外卖,外卖员把外卖送到家一样。快餐就是基本对象,module就是包装盒,provider就是袋子,外卖员就是component,用户点餐就是注入门牌号。

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

推荐阅读更多精彩内容