dagger2從入門到放棄-dagger.android
上一章中介紹了Activities Subcomponents Multibinding的實現過程,但是多出那麼多步驟還是讓人有些頭暈;而使用dagger.android可以簡化這一過程
使用
step1
需要引入"com.google.dagger:dagger-android:${dagger_version}"
如果需要注入SupportLib中的Fragment還需要引入"com.google.dagger:dagger-android-support:${dagger_version}"
引入註解處理器"com.google.dagger:dagger-android-processor:${dagger_version}"
step2
定義一個抽象的Module類,在裡面定義一個返回對應Activity使用@ContributesAndroidInjector的抽象方法
dagger.android會根據@ContributesAndroidInjector生成需要注入對應物件的SubComponent,並新增到map中
@Module public abstract class ActivitysModule { @ActivityScope//指定Subcomponent的生命週期 @ContributesAndroidInjector(modules = DaggerAndroidActivityModule.class)//指定DaggerAndroidActivity的Subcomponent中需要安裝的Module abstract DaggerAndroidActivity bindDaggerAndroidActivity(); }
這一步相當於完成了上篇文章中的step2、3、4、5,最終dagger.android會生成需要新增到map中的SubComponet.Builder
step3
將包含@ContributesAndroidInjector註解方法的Module和dagger.android提供的Module安裝到AppComponent中
@Component(modules = { AndroidInjectionModule.class, AndroidSupportInjectionModule.class, ActivitysModule.class,...}) public interface AppComponent { void inject(RealApplication application); }
step4
在Application中實現HasActivityInjector介面
public class RealApplication extends BaseApplication implements HasActivityInjector { @Inject DispatchingAndroidInjector<Activity> activityInjector; @Override public void onCreate() { super.onCreate(); DaggerAppComponent.builder() .baseAppModule(new BaseAppModule(this)) .build().inject(this); } @Override public AndroidInjector<Activity> activityInjector() { return activityInjector; } }
dagger.android還可以支援其他三大元件以及Fragment的注入,具體可以檢視DaggerApplication
的原始碼
step5
在activity中完成注入
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidInjection.inject(this); }
原理解析
看看AndroidInjection.inject(this)
到底幹了啥
public static void inject(Activity activity) { checkNotNull(activity, "activity"); Application application = activity.getApplication(); if (!(application instanceof HasActivityInjector)) { throw new RuntimeException( String.format( "%s does not implement %s", application.getClass().getCanonicalName(), HasActivityInjector.class.getCanonicalName())); } //因為application實現了HasActivityInjector,所以可以得到一個 AndroidInjector<Activity> activityInjector = ((HasActivityInjector) application).activityInjector(); checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass()); activityInjector.inject(activity); }
-
application中被注入的是
DispatchingAndroidInjector
-
其中持有了
Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories;
相當於SubComponent.Builder的map, -
DispatchingAndroidInjector實現了
AndroidInjector
,這裡的inject(T instance);
是通過獲取AndroidInjector.Factory構造可直接注入的AndroidInjector間接完成的注入
public interface AndroidInjector<T> { void inject(T instance); interface Factory<T> { AndroidInjector<T> create(T instance); } abstract class Builder<T> implements AndroidInjector.Factory<T> { @Override public final AndroidInjector<T> create(T instance) { seedInstance(instance); return build(); } @BindsInstance public abstract void seedInstance(T instance); public abstract AndroidInjector<T> build(); } }
AndroidInjector就比較好理解了,它其實就是一個SubComponent的下層介面,而AndroidInjector.Factory就是它的Builder
優點
大大簡化了Multibindings的實現過程
缺點
- 因為Multibindings的整個原理是面向抽象的,所以基於Multibindings的dagger.android也無法使用AndroidInjector.Factory提供其他的引數作為依賴的基礎
- dagger.android只支援四大元件和Fragment,對於ViewModel這種對於Multibindings有強烈需求的物件還不支援(立個flag,有官方支援應該也快了)