Android-Dagger2Android开发Android开发经验谈

Dagger2使用简析——简单注入

2019-05-20  本文已影响14人  白与兰与白兰地

NOTE1 : Dagger2的官网地址: https://google.github.io/dagger/

NOTE2 : 使用前请先了解JAVA中的注解基本知识,如果对实现原理感兴趣可以了解下APT技术(不了解也不影响正常使用)

一切实践从问题出发,首先我们来解决第一个问题,

1. 如何使用Dagger2注入一个简单对象到目标类中

让我们先复制一个示例,它包含下面三部分

@Module
public class MainModule {
    @Provides
    public Product provideProduct() {
        return new Product();
    }
}

@Component(modules = {MainModule.class})
public interface MainComponent {
    void inject(MainActivity activity);
}

public class MainActivity extends AppCompatActivity {
    @Inject
    Product mProduct;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...省略无关代码

        DaggerMainComponent
                .builder()
                .build()
                .inject(this);

        mProduct.create();
    }
}

我们依次对三个部分所涉及的内容进行解释:

1.1 @Module

@Module注解用于获取对象实例的类,Dagger2根据该注解知道应该去哪个类里获取对象实例

1.2 @Provides

@Provides注解用于module类中获取对象实例的方法,Dagger2根据该注解及方法的返回值类型将对象实例注入到对应的引用中

1.3 @Inject

@Inject用于注解构造函数或成员变量

1.4 @Component

@Component注解用于担任连接桥梁的接口,其两端分别是在@Component的参数中指定的modules数组在方法参数中指定的具体类
注意:方法参数必须是要注入的具体类,而非其父类或接口

1.5 DaggerMainComponent

在创建Module和Component后,我们需要build ——> Make Project,这样APT会在指定目录下生成对应的java文件,其中就会包含名如DaggerXX的的文件,它实现了我们所创建的Component接口,最终要完成注入,只需要像这样调用:

  DaggerMainComponent
                .builder()
                .build()
                .inject(this);

2. 简单分析自动生成的代码

2.1 DaggerXX类

public final class DaggerMainComponent implements MainComponent {
  private final MainModule mainModule;

  private DaggerMainComponent(MainModule mainModuleParam) {
    this.mainModule = mainModuleParam;
  }

  public static Builder builder() {
    return new Builder();
  }

  public static MainComponent create() {
    return new Builder().build();
  }

  @Override
  public void inject(MainActivity activity) {
    injectMainActivity(activity);
  }

  private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectMProduct(
        instance, MainModule_ProvideProductFactory.provideProduct(mainModule));
    return instance;
  }

  public static final class Builder {
    private MainModule mainModule;

    private Builder() {}

    public Builder mainModule(MainModule mainModule) {
      this.mainModule = Preconditions.checkNotNull(mainModule);
      return this;
    }

    public mainComponent build() {
      if (mainModule == null) {
        this.mainModule = new mainModule();
      }
      return new DaggerMainComponent(mainModule);
    }
  }
}

它实现了我们所创建的Component接口,内部使用了建造者模式,方便根据不同需求构建该对象实例,比如我们可以传入module实例替换默认的无参实例,关键看一下我们定义的inject方法的具体实现。

2.2 MainActivity_MembersInjector类和MainModule_ProvideProductFactory类

public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  //...省略无关代码

  public static void injectMProduct(MainActivity instance, Product mProduct) {
    instance.mProduct = mProduct;
  }
}
public final class MainModule_ProvideProductFactory implements Factory<Product> {
   //...省略无关代码

  public static Product provideProduct(MainModule instance) {
    return Preconditions.checkNotNull(
        instance.provideProduct(), "Cannot return null from a non-@Nullable @Provides method");
  }
}

其实关键的方法就是injectMProduct()provideProduct(),一看就懂,没什么可细说的。

3. 含有参数(依赖关系)的构造

Product必须与Worker关联时,有如下构造函数

 public Product(Worker worker) {
     mWorker = worker;
 }

此时我们提供Product实例对象时需要作出以下修改

@Provides
public Product provideProduct(Worker worker) {
    return new Product(worker);
}

即我们需要传入Worker来构建Product,那么Worker实例如何提供呢?其实同样的,我们可以使用简单构造时的两种方式提供Worker实例,具体就不在赘述,可以自行实践。

下一篇
,我们将对问题进行升级,并了解@Scope、@Qualifier、@binds、dependencies、Lazy的使用

上一篇下一篇

猜你喜欢

热点阅读