通過@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;
}