android Dagger2 @Module和@Provides 依賴注入

通過@Inject提供對象來依賴注入有以下兩個缺點

  • 如果要注入的對象屬於某個第三方庫中的類,那麼我們是無法在在這個類的構造方法上添加@Inject註解的
  • 如果要注入的對象是個abstract抽象類或者Interface接口,那麼這個類似沒有構造方法的,也無法添加@Inject註解

要解決以上問題,這時候就需要@Module和@Provides這對好基友上場了

二話不說,直接上代碼

public interface Person {
    String saySomething();
}
public class Student implements Person {

    public String name;

    // 這邊不需要再用@Inject了
    public Student() {
        this.name = "野猿新一";
    }

    @Override
    public String toString() {
        return String.format("我的名字叫%s啦", name);
    }

    @Override
    public String saySomething() {
        return toString();
    }
}
@Module
public class MainModule {
    // 注意返回類型要明確是Person,而不能是子類Student
    // 這裏我們就能夠提供了一個接口的實例了
    @Provides
    public Person providePerson() {
        return new Student();
    }
}
// 這裏記得加載module
@Component(modules = MainModule.class)
public interface MainActivityComponent {
    void inject(MainActivity activity);
}
public class MainActivity extends AppCompatActivity {

    // 這裏聲明的是一個接口
    @Inject
    Person person;

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

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

運行結果,成功注入了Person對象

生成代碼解析

Dagger爲我們生成了很多代碼,我們看下注入的流程

DaggerMainActivityComponent和MainActivity_MemberInjector在前面的文章中已經有介紹就不黏貼了

我們這次主要看下跟@Module和@Provides有關的MainModule_ProvidePersonFactory的代碼,代碼很簡單,通過module來提供注入的對象

public final class MainModule_ProvidePersonFactory implements Factory<Person> {
  private final MainModule module;

  public MainModule_ProvidePersonFactory(MainModule module) {
    this.module = module;
  }

  @Override
  public Person get() {
    return provideInstance(module);
  }

  public static Person provideInstance(MainModule module) {
    return proxyProvidePerson(module);
  }

  public static MainModule_ProvidePersonFactory create(MainModule module) {
    return new MainModule_ProvidePersonFactory(module);
  }

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

我們再看下整個的注入流程的代碼

DaggerMainActivityComponent.create().inject(this);

 DaggerMainActivityComponent中的相關代碼

DaggerMainActivityComponent內部的建造器,Module在這裏生成

public static final class Builder {
  private MainModule mainModule;

  private Builder() {}

  public MainActivityComponent build() {
    if (mainModule == null) {
      this.mainModule = new MainModule();
    }
    return new DaggerMainActivityComponent(this);
  }

  public Builder mainModule(MainModule mainModule) {
    this.mainModule = Preconditions.checkNotNull(mainModule);
    return this;
  }
}
@Override
public void inject(MainActivity activity) {
  injectMainActivity(activity);
}

@CanIgnoreReturnValue
private MainActivity injectMainActivity(MainActivity instance) {
  MainActivity_MembersInjector.injectPerson(
      instance, MainModule_ProvidePersonFactory.proxyProvidePerson(mainModule));
  return instance;
}

 MainModule_ProvidePersonFactory中的proxyProvidePerson()方法,返回由module提供的Person對象

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

MainActivity_MembersInjector中的injectPerson()方法,將提供的Person對象賦值給Activity的person成員變量,完成注入

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章