Dagger2系列之基本使用

前言

    项目中一直都在用Dagger2框架,但是没有系统的研究Dagger2的使用及原理,今天就来写一些关于Dagger2的一些文章,来记录自己研究Dagger2的过程及心得。本篇文章先介绍基本使用

起源

    研究之前先看一个问题。看如下两端段代码:类A

package com.dagger2app;

import android.util.Log;

/**
 * Created by xiaolong.wei on 2018/4/4.
 */

public class A {
    public void show(){
        Log.d("TAG", "show: this is A class");
    }
}

类A中只有一个方法show();

类MainActivity如下:

package com.dagger2app;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        A a = new A();
        a.show();
    }
}

类MainActivity中在onCreate方法中定义并初始化A类型的变量a,并调用a.show()方法。这样MainActivity和A就有了依赖关系,MainActivity类依赖A。如果项目庞大,这种依赖关系会变多,导致类与类之间耦合度增高。将来APP更新发版,极有可能导致“牵一发动全身”的情况,例如:如果有很多依赖A类的类,现在需要修改A类的构造,在构造函数中传一个参数,这样会导致,所有依赖A类的类都需要做响应的修改,导致风险变高,为了解决这种问题,Dagger2横空出世。

Dagger2引入

在Android项目的build.gradle中引入

dependencies {
  compile 'com.google.dagger:dagger:2.x'
  annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}

接下来就可以愉快的使用Dagger2了,有以下两种方式可以提供依赖:

1、方式一:

修改上面的代码,在需要提供依赖的类中,给构造增加注解标识,表明它需要提供依赖,修改代码如下

package com.dagger2app;

import android.util.Log;

import javax.inject.Inject;


/**
 * Created by xiaolong.wei on 2018/4/4.
 */

public class A {

    @Inject
    public A (){

    }

    public void show(){
        Log.d("TAG", "show: this is A class");
    }
}

然后新建Component标注的接口,此接口是依赖注入的管理类,也是连接依赖(A类)与目标类(MainActivity类)的桥梁;新建接口或抽象类,并用@Component标志注解,定义方法,方法名随意,不过建议方法名为inject,参数为需要被注入的类(MainActivity):

package com.dagger2app;

import dagger.Component;

/**
 * Created by xiaolong.wei on 2018/4/4.
 */

@Component
public interface ModuleInjector {

    void inject(MainActivity mainActivity);
}

新建完此接口后,需要build一下工程,Dagger2会帮我们自动生成此接口的实现类命名为DaggerXXX.class,其中XXX为你定义接口的名字,在这里就是DaggerModuleInjector。

接下来在MainActivity中修改a变量的声明方式,通过@Inject表明需要依赖的类,并获取DaggerModuleInjector实例,调用inject方法吧依赖注入进来,如下:

package com.dagger2app;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import javax.inject.Inject;

public class MainActivity extends AppCompatActivity {

    @Inject
    A a;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerModuleInjector.create().inject(this);//获取DaggerModuleInjector实例,调用inject方法
        a.show();
    }
}

以上就是Dagger2的第一种使用方式。

2、方式二

第三方库,不能修改源码,无法在构造方法中通过@Inject注解的方式提供依赖,这种情况下,就使用方式二。

假设类B为第三方库,不能修改源码:

package com.dagger2app;

import android.util.Log;


/**
 * Created by xiaolong.wei on 2018/4/4.
 */

public class B {
    
    public B(){

    }

    public void show(){
        Log.d("TAG", "show: this is B class");
    }
}

如果想通过Dagger2,把MainActivity对B类的依赖注入进去应该怎么做呢?

首先创建一个可以提供实例的类,类名如叫AppModule

package com.dagger2app;

import android.content.Context;

import dagger.Module;
import dagger.Provides;

/**
 * Created by xiaolong.wei on 2018/4/4.
 */

@Module
public class AppModule {

    @Provides
    B provideB(){
        return new B();
    }
}

此类通过@Module注解,在类中定义方法,命名方式一般为proviceXXX的形式,当然也可以看心情随便写,但是此方法必须用注解@Provides去标注,并在方法中返回需要提供依赖的实例。

接下来需要把这个Module加入到Component中,即用@Component标注的接口中

package com.dagger2app;

import dagger.Component;

/**
 * Created by xiaolong.wei on 2018/4/4.
 */

@Component(modules = AppModule.class)
public interface ModuleInjector {

    void inject(MainActivity mainActivity);
}

在@Component后面通过(modules=AppModule.class)的形式(如果是多个Module,需要写为(modules={XXXModule.class,YYYModule.class}))加到Component中,

接下来在需要引用B类的类中。通过@Inject的方式去注解声明,形式同方式一中的类A

以上就是Dagger2的基本使用方式

总结

出现四个注解

@Inject:可以注解在需要提供依赖的类的构造方法里,表明需要提供依赖;也可以注解在需要被注入的类的属性上,表明是注入进来的实例

@Component:通过此注解标注的接口,是连接提供依赖的类和需要依赖的类的桥梁

@Module:通过此标注的类,可以另一种方式提供依赖

@Provide:通过此标注注解的方法,需要返回提供依赖的实例

拓展

1、如果提供依赖的类,又依赖另外一个类,则另外一个类也需要通过@Inject或者@Module的方式提供依赖

2、两种方式的优先级是Module的方式大于@Inject的方式:如果@Module方式查找到了提供的依赖,则不再去查找@Inject方式是否有提供依赖了

你可能感兴趣的:(Android技术总结)