dagger2

作者: Mr_468 | 来源:发表于2017-03-13 10:12 被阅读0次

    研究dagger2两天,这里结合dagger2生成的代码分析下。

    component

    是一个接口。

    向外暴露获取实例的方法。

    可以用dependencies依赖别的component,用modules包含模块。component的返回实例的方法要么在依赖的component的modules里有providers标注的方法获取,要么在自己被inject标注的构造方法获取。modules优先级比inject高。如果依赖的component里(此处指接口里的方法,无论component包含的modules里有没有)和包含的module里同时有两个方法获取一样的实例,那么会报重复绑定的错。 如果要实例化的类里有两个构造方法被inject标注,会报只能包含一个标注的错。 如果component依赖的component上有scope标注,则必须和它的scope标注一致,否则报错 如果component包含的module中的方法上有scope标注,则必须和component上的scope一致,否则报错。 编译期dagger2生成对应的实现类Dagger***component的代码。实现类里有builder内部类。利用创建者模式初始化包含的模块。如果module只有含参构造,并且这个参数不能自动注入,(可以在参数需要使用的构造方法上标注@inject以保证在注入时使用该方法,如果不标注默认使用无参构造??好像不是这样)那么在获取component时必须设置这个参数。依赖的component也必须设置注入。 依赖的component的modules中

    返回值为void的方法

    这类方法内部实现都是这样


    injector的injectMembers方法就是注入需要注入的实例以及递归注入父类的实例,直到父类不再需要注入实例为止

    返回值为子组件

    也就是是返回值为被SubComponent标注的接口。
    这种方式跟用dependencies依赖的组件相似。

    inject

    Error:(19, 10) 错误: presenter.MainPresenter cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
    MainActivity.mainPresenter
    [injected field of type: presenter.MainPresenter mainPresenter]
    如果要在一个类中用inject标注注入变量,有两种方式。
    1.在这个变量的构造方法上用inject标注
    2.在module中用provides标注
    否则编译会报错,就是有无参构造也会报错。

    module

    module 类似一种工厂模式。module有的方法,component不必须有,这类方法没有暴露出去,外部拿不到实例,类似被private修饰。但component有的方法,要么必须有被providers标注的方法,要么必须有被inject标注的构造方法,这类方法外部可以拿到实例。

    scope

    自定义的接口。用在component 和 module中的提供实例的方法上。(能不能用在被inject标记的构造方法上?)
    以系统自带的singleton为例。看代码。


    看代码通过appcomponent的getContext,getNavigator等方法获取的实例实际是由providerContextProvider,provideNavigatorProvider等provider的get方法提供的。这些provider是哪里来的?(根据module中的方法名直接生成的这些类名真丑,module中的方法名应该去掉provide这个单词。。。)
    看initialize方法,appmodule中被singleton标注的方法provideContext和provideNavigator由ScopeProvider.create(factory.create(module))生成provider;而没有被singleton标记的provideToastUtil直接由factory.create(module)生成provider。
    再看看这两种provider的get方法有什么区别。 factory的get方法是直接返回了module里的实例化方法中注入的实例。 ScopeProvider的create方法是根据给定的factory创建一个provider。它的get方法里会判断被获取的实例有没有初始化。如果没有初始化,走factory的get方法,返回的对象即是module中方法返回的对象;如果初始化了,直接返回这个对象,不走factory的get方法。也就是说对返回的实例进行了单例处理。
    看看自定义的scope和系统自带的singleton,除了类名没有区别。(默认情况下注解是不会在javadoc文档中出现的,被Documentd标注的注解会出现在文档中,对程序没影响)自定义不同的scope只是为了用不同的类名提高代码的可读性。 综上,scope的作用是对module中方法返回的对象进行指定区域内的单例处理。这个区域就是被相同scope标注的comopnent对象。module里被scope标注的方法返回的对象在同一个component实例中都是单例的。
    验证结论
    context1和context2_1相同是因为getContext返回的对象是application,appclication肯定只有一个。所以,我们不用scope标注,在module的方法中也可以做单例处理。

    dagger2的作用是减少创建对象的重复代码,构建清晰的代码结构。

    相关文章

      网友评论

          本文标题:dagger2

          本文链接:https://www.haomeiwen.com/subject/aypvettx.html