Dagger2初体验的一点思考与实践

来源:互联网 发布:水果店软件 编辑:程序博客网 时间:2024/05/22 15:29

上一篇介绍了如何简单使用Dagger2,主要介绍了@Inject注解和@Component注解。再来重新理一下使用流程:

  1. 在MainActivity中使用@Inject注解变量User
  2. 在User.java的构造器中添加@Inject注解
  3. 创建类UserComponent并使用@Component注解此类
  4. 在UserComponent中添加bind(MainActivity activity)方法
  5. 编译工程,并在MainActivity中使用DaggerUserComponent.builder().build().bind(this);添加依赖注入

虽然实现效果是没有什么问题,但是在完成demo的过程中一直有几个问题困扰着我

  1. UserComponent中声明的方法为什么叫bind,改用别的名称会有问题吗?
  2. 假如在User中有多个构造器,并都使用@Inject注解了,那Dagger会使用哪个构造器实例化对象呢?
  3. 加入User中被@injec注解的构造器含有参数,那Dagger又会怎样实例化对象呢?
  4. 如果在User中将一个非构造器的方法使用@Inject注解会怎样呢?

问题1, 答案是否定的

在UserComponent中的方法可以取任何名称。我们可以查看编译之后生成的DaggerUserComponent.java中找到答案。

我在UserComponent.java中新加了一个方法aaa(MainActivity activity),如下所示:

@Singletonpublic interface UserComponent {    void bind(MainActivity mainActivity);    void aaa(MainActivity mainActivity);}

然后点击编译,生成DaggerUserComponent类,点进去看一下自动生成的代码如下:

@Override  public void bind(MainActivity mainActivity) {    mainActivityMembersInjector.injectMembers(mainActivity);  }  @Override  public void aaa(MainActivity mainActivity) {    mainActivityMembersInjector.injectMembers(mainActivity);  }

可以看到在DaggerUserComponent中的bind方法和aaa方法都是一样的,所以方法名取什么并不重要

问题2 答案是在一个类中只能有一个被@Inject注解的构造器,否则编译报错

同样在UserComponent中新加一个带String参数的构造器,并使用@Inject注解,重新编译会报如下错误:
这里写图片描述

问题3 答案是如果Dagger调用一个带参数的构造器(A)时,会继续查找该参数是否有被@Inject注解的构造器(B),如果有就使用该构造器(B)实例化对象,并传递给上一个构造器(A).

新建类Vip.java,如下所示:

public class Vip {    @Inject    public Vip() {        Log.e("DANNY", "Vip default construction called");    }}

然后修改User.java,创建带Vip参数的构造器,并使用@Inject注解

@Inject    public User(Vip vip) {        Log.e("DANNY", "construction with vip param called");    }

最后编译运行,在Logcat中可以看到如下log
这里写图片描述

对于问题4 答案很有意思,如果在一个类中除了构造器之外,有其他非构造器也被@Inject注解,那Dagger会在调用完构造器之后,自动调用此方法

比如在User中添加如下修改

@Inject    public User(Vip vip) {        Log.e("DANNY", "construction with vip param called");    }    @Inject    public void init2() {        Log.e("DANNY", "init2 is called");    }    @Inject    public void init() {        Log.e("DANNY", "init is called");    }

可以看到,除了构造器之外,又重新添加了两个被@Inject注解的方法,分别为init2和init。 然后编译并运行工程可以看到如下log
这里写图片描述
从log中可以看到,虽然init2和init方法并没有在User中主动调用,但是Dagger会找到被@Inject注解的方法 自动调用,并且是按照从上往下的顺序调用

原创粉丝点击