Android Dagger2 @Component的dependencies属性用法

 一个Component可以通过dependencies依赖另一个Component,可以获取到另一个Component提供的依赖

具体代码如下:

public interface Person {
    String saySomething();
}

public class Student implements Person {

    public String name;

    public Student() {
        this.name = "野猿新一";
    }

    @Override
    public String saySomething() {
        return String.format("我的名字叫%s啦", name);
    }
}
@Module
public class PersonModule {
    @Provides
    public Person providePerson() {
        return new Student();
    }
}

 注意这里为Person单独创建了一个Component然后依赖PersonModule,而不是直接把PersonModule设置给MainActivityModule

而且里面的getPerson()方法单纯提供Person对象,不像MainActivityModule中的inject()方法用于注入

@Component(modules = PersonModule.class)
public interface PersonComponent {
    Person getPerson();
}

 这里有别于依赖于Module的写法@Component(modules = PersonModule.class),而是直接依赖PersonComponent

@Component(dependencies = PersonComponent.class)
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

 这里需要注意的是personComponent()方法必须调用且传递一个PersonComponent对象进入,否则在运行时会报如下错误

实现代码

Caused by: java.lang.IllegalStateException: com.him.hisapp.PersonComponent must be set
        at com.him.hisapp.DaggerMainActivityComponent$Builder.build(DaggerMainActivityComponent.java:45)
        at com.him.hisapp.MainActivity.onCreate(MainActivity.java:20)
        at android.app.Activity.performCreate(Activity.java:6041)
public class MainActivity extends AppCompatActivity {

    @Inject
    Person person;

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

        DaggerMainActivityComponent.builder()
                .personComponent(DaggerPersonComponent.create())
                .build()
                .inject(this);
        TextView textView = findViewById(R.id.text);
        textView.setText(person.saySomething());
    }
}

 DaggerMainActivityComponent源码解析

我们主要看下Dagger为我们生成的DaggerMainActivityComponent的源码,里面依赖了PersonComponent

在Builder.build()方法调用是会判断personComponent是否为空,空的话会抛异常,至于为什么不在为空的时候直接new一个DaggerPersonComponent出来目前我还不知道原因,还请有知道的读者评论说明下

public final class DaggerMainActivityComponent implements MainActivityComponent {
  private PersonComponent personComponent;

  private DaggerMainActivityComponent(Builder builder) {
    initialize(builder);
  }

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

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {
    this.personComponent = builder.personComponent;
  }

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

  @CanIgnoreReturnValue
  private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectPerson(
        instance,
        Preconditions.checkNotNull(
            personComponent.getPerson(),
            "Cannot return null from a non-@Nullable component method"));
    return instance;
  }

  public static final class Builder {
    private PersonComponent personComponent;

    private Builder() {}

    public MainActivityComponent build() {
      if (personComponent == null) {
        throw new IllegalStateException(PersonComponent.class.getCanonicalName() + " must be set");
      }
      return new DaggerMainActivityComponent(this);
    }

    public Builder personComponent(PersonComponent personComponent) {
      this.personComponent = Preconditions.checkNotNull(personComponent);
      return this;
    }
  }
}

注入的流程

我们再看下Dagger为我们生成的代码再注入的整个过程中做了哪些工作

首先从MainActivity中调用DaggerMainActivityComponent.inject()开始,记得必须调用personComponent设置依赖的Component

DaggerMainActivityComponent.builder()
                .personComponent(DaggerPersonComponent.create())
                .build()
                .inject(this);

 看下DaggerMainActivityComponent中的Builder代码,卡夏是如何设置personComponent的和在build()的时候如果personComponent为空会抛出异常

public static final class Builder {
    private PersonComponent personComponent;

    private Builder() {}

    public MainActivityComponent build() {
      if (personComponent == null) {
        throw new IllegalStateException(PersonComponent.class.getCanonicalName() + " must be set");
      }
      return new DaggerMainActivityComponent(this);
    }

    public Builder personComponent(PersonComponent personComponent) {
      this.personComponent = Preconditions.checkNotNull(personComponent);
      return this;
    }
  }

 DaggerMainActivityComponent的inject()方法内部调用了injectMainActivity()方法

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

 DaggerMainActivityComponent的injectMainActivity()方法内部调用了MainActivity_MembersInjector.injectPerson()方法来完成Person的依赖注入,传入MainActivity对象和一个Person实例,而这个Person实例就是由PersonComponent的gerPerson()方法提供的

@CanIgnoreReturnValue
private MainActivity injectMainActivity(MainActivity instance) {
  MainActivity_MembersInjector.injectPerson(
      instance,
      Preconditions.checkNotNull(
          personComponent.getPerson(),
          "Cannot return null from a non-@Nullable component method"));
  return instance;
}

 我们在看下DaggerPersonComponent的getPerson()方法,里面调用了PersonModule_ProvidePersonFactory.proxyProvidePerson()

@Override
public Person getPerson() {
  return PersonModule_ProvidePersonFactory.proxyProvidePerson(personModule);
}

 看下PersonModule_ProvidePersonFactory.proxyProvidePerson()方法内部就明白了Persong对象最终是由PersonModule提供的

public static Person proxyProvidePerson(PersonModule instance) {
  return Preconditions.checkNotNull(
      instance.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
}

最终再看下MainActivity_MembersInjector.injectPerson()方法,里面把生成的person对象赋值给MainActivity的person变量,最终完成依赖的注入

public static void injectPerson(MainActivity instance, Person person) {
  instance.person = person;
}

总结以上的注入流程就是

MainActivityComponent依赖PersonComponent

PersonComponent依赖PersonModule

所以最终的Person对象是由Module提供的

你可能感兴趣的:(Dagger2,Android,Dagger2,依赖注入)