Dagger2实用教程(1):初识Component

在你读这篇文章时,我假设你已经知道了使用Dagger有什么好处,下面我们开门见山。本偏讲述的是Dagger2的HelloWorld。希望读者通过本篇文章能了解Dagger2最基本的用法。

1. 添加依赖

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

第一个依赖中包含了要使用到的类,第二个依赖用于编译和生成代码。

2. 创建Component

写一个空的Component,这个Component可以是接口或者抽象类,必须使用@Component标注。

@Component
public abstract class HelloComponent {


}

3. 生成DaggerComponent

rebuild工程,前往app/build/source/apt/debug/yourpackage下面找到相应的Dagger*Component类,比如我用上述的HelloComponent,rebuild之后得到一个DaggerHelloComponent类:

public final class DaggerHelloComponent extends HelloComponent {
  private DaggerHelloComponent(Builder builder) {}

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

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

  public static final class Builder {
    private Builder() {}

    public HelloComponent build() {
      return new DaggerHelloComponent(this);
    }
  }
}

Dagger基于@Component标注的类,使用注解处理器生成了一个该类的实现类。该类以”Dagger”与@Component注解类的类名进行驼峰组合命名,是@Component注解类的实现类。它内置了构造器Builder.

通过DaggerHelloComponent.create()可以得到HelloComponent类型的DaggerHelloComponent实例。
通过DaggerHelloComponent.builder()可以得到DaggerHelloComponent.Builder的实例,进而通过build()方法,即DaggerHelloComponent.builder().build()也能得到HelloComponent类型的DaggerHelloComponent实例。

目前来看上述两种获取AppComponent实例的方法是等效的。那它们究竟有什么区别呢?这个我们留在后面再说。
目前,我们虽然能得到由HelloComponent实例,但是很显然,我们用它什么都干不了。

4. 添加Component方法

根据官方API,Dagger的Component必须至少包含一个抽象的Component方法(否则就像上面这样,Component啥用也没有)。所谓Component方法,指的是Provision方法或者Members-Injection方法
+ Provision方法
Provision方法类似于Bean类的Getter方法,是一种无参方法,该方法返回一个injected或者provided类型

  • Members-Injection方法
    Members-Injection方法类似于Bean类的Setter方法,但是它并不是把入参传给Component,而是将Component可提供的对象传给入参的成员。Members-Injection方法的名字任意,格式正好与Provision方法相反,有参数无返回值。使用Members-Injection方法,Component会向Client类使用@Inject修饰的成员提供对象。

下面以injected类型为例,讲述两种Component方法的不同用法。最简单地,通过@Inject修饰一个具体类的无参构造函数就可以得到一个injected类型了。例如下面的User

public class User {

    private String mName;

    @Inject
    public User() {
        mName = "JingKe";
    }

    public String getName() {
        return mName;
    }

    public void setName(String name) {
        mName = name;
    }

    public void say(){
        Log.e("User","Hello, I'm "+mName+", I am using a Dagger");
    }
}

rebuild,注解处理器根据@Inject修饰的User生成一个User_Factory类如下:

public final class User_Factory implements Factory<User> {
  private static final User_Factory INSTANCE = new User_Factory();

  @Override
  public User get() {
    return new User();
  }

  public static User_Factory create() {
    return INSTANCE;
  }
}

4.1 使用Provision方法

  • HelloComponent中添加一个返回injected类型的抽象的Provision方法:

    @Component
    public abstract class HelloComponent {
    
        abstract User getUser();
    }
  • rebuild工程,在app/build/source/apt/debug/yourpackage目录下,Dagger为我们生成新的DaggerHelloComponent:

    public final class DaggerHelloComponent extends HelloComponent {
      private DaggerHelloComponent(Builder builder) {}
    
      public static Builder builder() {
        return new Builder();
      }
    
      public static HelloComponent create() {
        return new Builder().build();
      }
    
      @Override
      User getUser() {
        return new User();
      }
    
      public static final class Builder {
        private Builder() {}
    
        public HelloComponent build() {
          return new DaggerHelloComponent(this);
        }
      }
    }

    新的DaggerHelloComponent也覆盖了我们在HelloComponent中添加的抽象的Provision方法,返回User对象。

  • 使用DaggerHelloComponentProvision方法获取对象:

    public class ComponentActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_component);
            DaggerHelloComponent.create().getUser().say();
        }
    }

4.2 使用Members-Injection方法

  • Component中新建Members-Injection方法:

    @Component
    public abstract class HelloComponent {
    
    //    public abstract User getUser();
    
        public abstract void inject(ComponentActivity injectionActivity);
    
    }

    rebuild,生成新的DaggerHelloComponent:

    public final class DaggerHelloComponent extends HelloComponent {
    
      //...
    
      @Override
      public void inject(ComponentActivity injectionActivity) {}
    
      //...
    }
    

    这时候我们发现,除了重写了inject()抽象方法,给出一个空实现,并没有什么变化。看官别急,继续往下看:

  • Client类中,添加可注入成员,并用@Inject修饰,这里需要注意在使用这些对象之前,必须调用Members-Injection方法注入这些对象:

    public class ComponentActivity extends AppCompatActivity {
    
        @Inject
        User mUser;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_hello_component);
    //      DaggerHelloComponent.create().getUser().say();
            DaggerHelloComponent.create().inject(this);
            mUser.say(); 
        }
    }
    
  • 这一次rebuild之后,我们会发现,build目录下增加了一个ComponentActivity_MembersInjector类:

    public final class ComponentActivity_MembersInjector implements MembersInjector<ComponentActivity> {
      private final Provider<User> mUserProvider;
    
      public ComponentActivity_MembersInjector(Provider<User> mUserProvider) {
        this.mUserProvider = mUserProvider;
      }
    
      public static MembersInjector<ComponentActivity> create(Provider<User> mUserProvider) {
        return new ComponentActivity_MembersInjector(mUserProvider);
      }
    
      @Override
      public void injectMembers(ComponentActivity instance) {
        injectMUser(instance, mUserProvider.get());
      }
    
      public static void injectMUser(ComponentActivity instance, User mUser) {
        instance.mUser = mUser;
      }
    }

    DaggerHelloComponent也有了实质性的变化:

    public final class DaggerHelloComponent extends HelloComponent {
      private DaggerHelloComponent(Builder builder) {}
    
      public static Builder builder() {
        return new Builder();
      }
    
      public static HelloComponent create() {
        return new Builder().build();
      }
    
      @Override
      public void inject(ComponentActivity injectionActivity) {
        injectComponentActivity(injectionActivity);
      }
    
      private ComponentActivity injectComponentActivity(ComponentActivity instance) {
        ComponentActivity_MembersInjector.injectMUser(instance, new User());
        return instance;
      }
    
      public static final class Builder {
        private Builder() {}
    
        public HelloComponent build() {
          return new DaggerHelloComponent(this);
        }
      }
    }

    从以上可以看出,Client类中的@Inject成员会对DaggerCompoent的生成产生影响。注解处理器根据@Inject成员生成当前Client类的成员注入器,DaggerComponent通过用户声明的inject()方法传参Client和依赖,然后注入器将依赖设置到Client的成员,完成成员对象的注入。

两种Component方法最后达到了同样的目的,如下是打印结果:

E/User: Hello, I'm JingKe, I am using a Dagger

总结

本篇文章讲述了Dagger2最基本的用法,概括为以下步骤:
1. 创建Component
2. 提供injectable类或者provided对象
3. 添加Component方法,Component方法包括Provision方法和Members-Injection方法。
4. 使用Component提供或注入依赖到Client类。

下一节我们讲injected类型之@Inject.

猜你喜欢

转载自blog.csdn.net/kevinscsdn/article/details/79135074