Dagger2的实际使用

前言

Dagger2是依赖注入的框架,网上有很多关于dagger的使用方法。好处想必大家都能知道就是解耦。 那解谁和谁耦合呢?就是对象实例化和使用宿主的耦合。

我看了网上有很多使用的说,说Dagger多好,比原有多写了一大堆代码,然后说框架好解耦。说实话我看了他们的代码没觉得有多好, 为了达到某一个目的,饶了一大圈, 我不愿意。我写代码喜欢简洁优雅,用框架无非就是用少量的代码实现更好的结构。如果非需要,写一大堆让人眼花缭乱的代码证明自己有多diao,好吧,你赢了。

废话不扯了,今天主要讲讲我对Dagger2实际使用的理解。

实际使用

首先简单说说Dagger2,比较懒,用网上一张图标识( 如下图 )

《Dagger2的实际使用》

上图比较清晰的展示了Dagger2的结构。我来人物角色介绍一下:

Module: 实例化工厂类. 类似于医院的药房,有中药房,西药房等,专门负责提供药品的。

Component: 注入器。类似于护士,护士帮病人拿药,去哪拿呢,去上面的药房。

Container:宿主,被注入的对象。 类似于病人,你需要要什么药?写个清单( 就在你的变量上面用    @Injectde标记一下) 叫上面的护士帮你拿药。

问题来了,病人( Container )请护士( Component )拿药,他希望找一个还是多个呢?

有人说,得分开,西药的西药房护士拿,中药让中药房护士拿…. 累不累,病人管你什么类型的药,那是你医院为了管理分的类别。就找一个护士,你具体怎么拿药,流程多复杂,那是你的事情。

OK,Container中只需要一个Component来注入。

讲到这,我得画张图 ( 当然没有网上的大牛画的好看,我是画板画的 ),上面的图只是Dagger的结构,实际使用的有点出入:

《Dagger2的实际使用》

在实际使用中,病人( Container )不止一个,那需要多少个护士( Component )呢?有人说1个病人一个护士,哪个医院那么好,提供1对1的VIP服务。

我们写App,现在就是医院领导,你希望聘用几个护士呢? 我希望是越少越好,如果一个能干活的最好,写那么多干嘛,浪费我手敲代码。

问题来了,需要几个护士( Component )呢?

我也不知道几个,作为app的构造者,不能这样。那怎么办,咱们从下往上看,看看需要几个护士干活不就行了。

那么多病人( Contaniner )需要要很多种药( 需要注入的对象 ),我们来给这些药分类下。需要注入的对象我们根据实例化需要参数的不同分不同类。例如 

NetworkHelper(Context context)

ToastUtils(Context context)

DBUtils(参数1 a , 参数2 b)

XXXDao(参数1 a , 参数2 b)

为什么要这么分呢,因为对象实例化需要的参数是通过Module工厂类的构造方法传进去的。所以需要Context参数的,就放在 ModuleA(Context ctx) 这个工厂类里面产生。

有人说我不懂哦? 就是例如 有些药需要提供医生的处方才能取的,我把他们放在一个药房,有些需要实名认证的,我也放在一个药房。有些直接付钱就能取药的,例如无参的对象。

还好安卓简单一些,一般需要注入的对象,无非就是分2种,需要上下文对象的 和 无参的。当然我一般会定义4个Module, 前2个是搭框架的时候,需要的注入常规的,后2个是实际业务需要的注入的。其实还是2个,只不过把共用的提出来。 

有人说,我注入的对象例如 DialogUtil(Context cxt , String title),每次使用String都传的不一样,怎么办? 大哥不带这么玩的,title属于具体到某个业务场景了,你就不能DialogUtil(Context cxt) , 然后 DialogUtil.set(String title)

结论有了,Module数量 >= 2个,安卓一般就2个,ModuleA(Context ctx) 和 ModuleB( )。

跑题是吧,问题是护士需要几个?

那我们再来问一次,需要几个护士( Component )呢?

理论上其实一个就够了。

但是Dagger有个注解@Scope @Singleton,提到了生命周期。哦?Dagger作为医院,他其实是药品的储存的容器,他还有一个功能,就是管理所有注入变量的生命周期。这个好理解,例如酒精 消毒的,你每次去医院消毒不会买瓶酒精吧,这个是共用的全局变量。 有些药是一次性。

那我们的App,注入实例有哪几种生命周期呢,我这分为4个 ==> 1. @Application  全局的  2. 和宿主生命轨迹一样 3. 注入到宿主后,用到了就产生,用不到就不会实例化  4. 一次性的,每次都是新的。

作为医院的领导,聘用护士当然也分了,有的签的是永久制合同,有的签的是临时合同,还有的是实习生。

为什么要这么分呢,注入实例的生命周期是跟护士是有关的。如果你用@Scope标识工厂类产生实例A的方法,那就说明这个实例A的生命周期和他那个Component生命周期一样。全局的护士当然拿的药品A就是全局的,咱们下一篇可以看看Dagger帮我们自动生成的Component的实现类。

那我们看看上面的4中生命周期的注入对象怎么实现呢?

1. @Application  全局的对象   我们就不要用什么单例了, 用全局的Component就可以了。

                          那全局的Component怎么实现呢?在Application只初始化一次就行了

2. 和宿主生命轨迹一样   就是正常的 @Inject

3. 注入到宿主后,用到了就产生,用不到就不会实例化   这个在注入的时候

                         用Lazy<需要注入的对象>

4. 一次性的,每次都是新的。 用 Provider<需要注入的对象>

1个Component能显示这四个么? 答案是肯定的,上代码

@Component(modules={ModuleA.class,ModuleB.class,ModuleC.class ….. })

@Application

public interface XXXComponent {

         void injectAAA(AAA aaa);

         void injectBBB(BBB bbb);

}

结论有了, Component数量 >= 1,我一般写1个

使用总结

综上所述,咱们在实际App开发中,Dagger的框架大致是如下:

《Dagger2的实际使用》

在谈谈耦合

咱们在Container里使用Compontent的时候,一般代码是如下:

MineComponent  component=DaggerMineComponent.builder().appModule(appModule).build();

component.injectXXX(this);

当你的Module不是无参的构造方法,Dagger框架需要你提供Module的实例。

呵呵,是不是感觉白忙活了是吧,刚减少对具体实例的依赖,现在对工厂类产生依赖。

我的做法是Component在Application里面生成。 然后用个静态方法,在具体宿主中取Component。

public class ComponentInject {

……….

   public static MineComponent getComponent() {

         return  inject.mineComponent;

   }

}

public XActivity extend AppCompatActivity {

     ….

    onCreate(Bundle savedInstanceState) {

         ComponentInject.getComponent().injectHome(this);

    }

}

先写这,下一篇咱们看看Dagger生成的代码。

    原文作者:维少
    原文地址: https://www.jianshu.com/p/fc4ed82fe75a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞