美文网首页
初识Dagger2

初识Dagger2

作者: zhengLH | 来源:发表于2019-04-22 23:33 被阅读0次

【相关链接】
(1)https://blog.csdn.net/shusheng0007/article/details/80950117
(2)https://www.jianshu.com/p/2cd491f0da01
(3)https://www.jianshu.com/p/5f11cacb6250
(4)http://www.jcodecraeer.com/a/anzhuokaifa/2018/0307/9471.html

【1】dagger2概念

【总结】主要是通过Java注解(Annotation)来工作。

图片.png

【通俗】是一个依赖注入框架,butterknife也是一个依赖注入框架。不过butterknife,最多叫奶油刀,Dagger2被叫做利器啊,他的主要作用,就是对象的管理,其目的是为了降低程序耦合。

图片.png

【2】什么是依赖注入

依赖注入是一种给一个对象提供其依赖的对象的技术。例如A对象需要依赖B对象,那么此处关键点就是不能在A里面去new B对象,必须通过某种方式将B对象提供给(注入)A中,例如最简单的方式是通过一个 set(B b)方法

【3】使用依赖注入和不使用依赖注入有什么区别呢?
【答案】其最主要的目的就是为了解耦,随即而来的就是可测试性,可维护,可扩展性就大大提高了。

【4】dagger2中最重要的就是Inject,Component,Module。

(A) Inject

图片.png

【注释】
(1)在A类中标记B类的字段:告诉dagger 我们要注入B类的实例到A类中,你帮我搞定(我王二狗要牛翠花,dagger2你帮我搞定)。

(2)在B类中标记B类的构造函数:告诉dagger B类是一个可以被注入的类,如果你想把B的实例对象注入到其他类中,例如注入到A类中,是没有任何问题的。

(B) Component

(1) 代码
@Component(modules = {DaggerModule.class})
public interface MatchComponent
{
void mainActivityInject(MainActivity activity);
}

(2)注释
Component 一般是一个使用 @Component标记的接口,其持有A类的实例,其在A类中发现有使用@Inject标记的属性b,就会去查找这个属性的类型B,然后调用其构造函数产生实例对象赋值给b。这样就完成了对A类中b属性的赋值,即完成了依赖注入。

(C)Module

C类是一个没有使用@Inject注解其构造函数的类,而且我们也无法加上,可能由于它是一个第三方类,或者其他原因。那我们想要使用dagger2将其注入到A类中就需要使用到Module。Module负责提供C类的实例对象,当Component发现了使用 @Inject注解的C类属性时,先去Module中查找,没有的话再去看其构造函数是不是使用@Inject标记了,如果都没有,注入失败。

【总结】Dagger 是通过@Inject使用具体的某个对象,这个对象呢,是由@Provides注解提供,但是呢,这个@Provides只能在固定的模块中,也就是@Module注解,我们查找的时候,不是直接去找模块,而是去找@Component。

【示意图】

图片.png

我们反向推到,当们使用
@Inject
A a

想要获取a对象的示例的时候,Dagger2 会先去找,当前Activity或者Fragment所连接的桥梁,例如上图中,连接的只有一个桥梁,实际上可以有多个,这个桥梁,会去寻找他所依赖的模块,如图中,依赖了模块A,和模块B,然后在模块中,会去寻找@Providers注解,去寻找A的实例化对象。

【集成】

图片.png

【1】依赖:

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

【2】开发步骤:

(1) 创建Moudule

    //   第一步 添加@Module 注解
        @Module
        public class MainModule {
              // todo
         }

(2)创建具体的示例:

// 第一步 添加@Module 注解
@Module
 public class MainModule {
//第二步 使用Provider 注解 实例化对象
@Provides
A providerA() {
    return new A();
    }
}

(3)创建一个Component接口:

 //第一步 添加@Component
 //第二步 添加module
 @Component(modules = {MainModule.class})
 public interface MainComponent {
//第三步  写一个方法 绑定Activity /Fragment
   void inject(MainActivity activity);
  }

(4)Rebuild Project

图片.png

然后AS 会自动帮我们生成一个:

图片.png

(5)将Component与Activity/Fragment绑定关系:

public class MainActivity extends AppCompatActivity {
  /***
   * 第二步  使用Inject 注解,获取到A 对象的实例
  */
  @Inject
  A a;

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

    /***
     * 第一步 添加依赖关系
     */
    //第一种方式
    DaggerMainConponent.create().inject(this);

    //第二种方式
    DaggerMainConponent.builder().build().inject(this);

    /***
     * 第三步  调用A 对象的方法
     */
    a.eat();
     }
}

【高级用法】

(1)构造方法需要其他参数时候:

图片.png

(2) 模块之间的依赖关系:

图片.png 图片.png

这样的话,Dagger会现在A moudule 中寻找对象,如果没找到,会去找module B 中是否有被Inject注解的对象,如果还是没有,那么GG,抛出异常。

(3)一个Component 应用多个 module:

图片.png

(4)dependencies 依赖其他Component:

图片.png

(5) @Named注解使用:

图片.png 图片.png

(6)@Singleton注解:单例模式,是不是超级方便,你想然哪个对象单利化,直接在他的Provider上添加@Singleton 就行了。

图片1.png 图片2.png

【思考】那有人就要问了,没什么办法么,我就想全局只要一个实例化对象啊? 办法肯定是有的。

(7)自定义Scoped:

图片.png

【总结】

图片.png

(8)lazy 和 Provider

图片.png

其中Lazy(懒加载)的作用好比component初始化了一个present对象,然后放到一个池子里,需要的时候就get它,所以你每次get的时候拿到的对象都是同一个;并且当你第一次去get时,它才会去初始化这个实例。

provider(强制加载)的作用:
1:同上当你第一次去get时,它才会去初始化这个实例
2:后面当你去get这个实例时,是否为同一个,取决于他Module里实现的方式

(9)Subcomponent: 当使用Subcomponent,那么默认会依赖Component

图片.png 图片.png

【架构1】 MVP + Dagger2

图片.png 图片.png 图片.png 图片.png

【架构2】MVVM+Retrofit+Dagger2

【扩展】

图片.png

【解答】http://www.jcodecraeer.com/a/anzhuokaifa/2018/0307/9471.html

相关文章

网友评论

      本文标题:初识Dagger2

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