MVVMArms系列 - 最新的 Dagger2.11(Dagger.Android) 多 Module 實戰詳解

xiaobailong24發表於2017-09-18

1 前言

距離首次接觸 Dagger2 已經有半年的時間了,從最初的一臉懵逼,到慢慢的熟練使用,這個過程真的感謝 MVPArms,這半年在 MVPArms 真的學到很多東西,由此演變出的 MVVMArms 可以說是這半年學習的結晶。其中在構建 MVVMArms 的過程中,採用了最新的 Dagger2.11,更好的支援了 Android 的依賴注入。好了,廢話就說這麼多,下面來通過一個例子來對 Dagger.Android 有更進一步的認識。

下載原始碼一起看會更好!下載原始碼一起看會更好!下載原始碼一起看會更好!

DaggerAndroid:github.com/xiaobailong…

如果你還沒接觸過 Dagger2,可以看我之前轉載的一篇文章 - Dagger2 學習,裡面概念講得很清晰。
目前大多數文章還是講解簡單使用 Dagger2,但是對於多 Module 下,怎麼通過 Dagger 管理他們之間的依賴關係,還沒有這樣的文章,我會把在 MVVMArms 中探索出的一種 Dagger.Android 多 Module 管理方案分享給大家。

2 Gradle 配置

要在 Android 中使用 Dagger2 , 先新增 Gradle 配置,最新的版本可在 GitHub 找到。這裡使用了 Android Studio 3.0 Beta6

  //dagger.android
  implementation 'com.google.dagger:dagger:2.11'
  annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
  implementation 'com.google.dagger:dagger-android:2.11'
  implementation 'com.google.dagger:dagger-android-support:2.11'
  annotationProcessor 'com.google.dagger:dagger-android-processor:2.11'複製程式碼

3 入門篇

先來看一下幾個關鍵的概念:

  • @Component: Component 是一個注入器,就像注射器一樣,Component 會把目標類依賴的例項注入到目標類中,來初始化目標類中的依賴。
  • @Subcomponent: 從名字可以看出,這也是一個注入器,只不過被 @Subcomponent 註解的是被 @Component 註解的下一層級,這就像 Subcomponent 繼承於 Component 一樣。
  • @Module: 為一些三方類庫提供注入的物件,常配合 @Provides 使用。
  • AndroidInjectionModule: 主要提供 Dagger.Android 元件包,它應該被包含在注入 Application 的 Component 注入器的 modules 中。
  • AndroidInjection: Dagger.Android 注入的核心類,主要封裝了一些靜態方法用來為四大元件和 Fragment 進行注入。

Dagger.Android 可以有兩種注入方式,下面分別通過 Activity 和 Fragment 來看一下。

3.1 Activity 依賴注入(第一種注入方式)

3.1.1 AndroidInjectionModule

在整個 Application 的 Component 中新增 AndroidInjectionModule
AndroidInjectionModule 主要提供 Dagger.Android 元件包,它應該被包含在注入 Application 的 Component 注入器的 modules 中。
此例中為 AppComponent。

AppComponent

  @Singleton
  @Component(modules = AndroidInjectionModule.class)
  public interface AppComponent {
      void inject(MainApp mainApp);
  }複製程式碼

這樣就可以確保使用最新的 Dagger.Android

3.1.2 @Subcomponent

為 Activity 編寫 Subcomponent,該介面需要繼承 public interface AndroidInjector;該介面內有一個被 @Subcomponent.Builder 註解的繼承於 AndroidInjector.Builder 的抽象類,其中泛型 T 為要注入的目標 Activity。

MainActivitySubcomponent

  @ActivityScope
  @Subcomponent(modules = KobeModule.class)//DataModule
  public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
      @Subcomponent.Builder
      abstract class Builder extends AndroidInjector.Builder<MainActivity> {
      }
  }複製程式碼

一些需要注入的資料型別可以包含在 @Subcomponent(modules = {}) 中。

KobeModule

@Module
  public class KobeModule {
      @ActivityScope
      @Provides
      public Person provideKobe() {
          return new Person("Kobe", 39);
      }
  }複製程式碼

Person

  public class Person {
      private String name;
      private int age;

      @Inject
      public Person(String name, int age) {
          this.name = name;
          this.age = age;
      }

      public String getName() {
          return name;
      }

      public int getAge() {
          return age;
      }
  }複製程式碼

3.1.3 @Module

接下來,編寫 Activity 的 Module,繫結上一步新建的 Subcomponent,這樣 MainActivitySubcomponent 就會為 MainActivity 注入 MainActivityModule 中提供的內容。
然後將其新增到全域性 Component 中,即上文中的 AppComponent,這樣 AppComponent 就和 MainActivitySubcomponent 建立了聯絡,這是一種繼承關係,即 Subcomponent 為 Component 的下一級。

MainActivityModule

  @Module(subcomponents = MainActivitySubcomponent.class)
  public abstract class MainActivityModule {
      /**
       * 第一種注入方式。需要 Subcomponent
       */
      @Binds
      @IntoMap
      @ActivityKey(MainActivity.class)
      abstract AndroidInjector.Factory<? extends Activity>
      bindActivityInjectorFactory(MainActivitySubcomponent.Builder builder);
  }複製程式碼

AppComponent 改寫為:

  @Singleton
  @Component(modules = {AndroidInjectionModule.class,
          MainActivityModule.class)
  public interface AppComponent {
      void inject(MainApp mainApp);
  }複製程式碼

3.1.4 HasActivityInjector

MainApp 實現 HasActivityInjector 介面,並注入 DispatchingAndroidInjector
為 Activity 提供 AndroidInjector,這是 AndroidInjection.inject(Activity activity) 所需要的,具體見 3.1.6 的原始碼解析。

MainApp

  public class MainApp extends Application implements HasActivityInjector {
      @Inject
      DispatchingAndroidInjector<Activity> mActivityInjector;

      private AppComponent mAppComponent;

      @Override
      public void onCreate() {
          super.onCreate();

          mAppComponent = DaggerAppComponent.builder()
                  .daggerComponent(getDaggerComponent())
                  .build();
          mAppComponent.inject(this);
      }

      public AppComponent getAppComponent() {
          return mAppComponent;
      }

      @Override
      public AndroidInjector<Activity> activityInjector() {
          return mActivityInjector;
      }
  }複製程式碼

3.1.5 AndroidInjection

最後,在目標 Activity 的 onCreate() 方法中進行注入,需要注意的是應該在 super.onCreate() 呼叫前注入。

MainActivity

  public class MainActivity extends AppCompatActivity {
    @Inject
    Person mKobe;//依賴注入

    public void onCreate(Bundle savedInstanceState) {
      AndroidInjection.inject(this);
      super.onCreate(savedInstanceState);
    }
  }複製程式碼

最後不要忘記在 AndroidManifest.xml 中指定 MainApp

3.1.6 原始碼解析

AndroidInjection.inject()MainApp 獲得一個 DispatchingAndroidInjector 物件,並將 MainActivity 傳入到 inject(Activity activity) 方法。 DispatchingAndroidInjector 為 MainActivity 類查詢 AndroidInjector.Factory 的實現類,即 MainActivitySubcomponent.Builder;接著會建立一個 AndroidInjector,即 MainActivitySubcomponent,並將 MainActivity 傳入到 inject(Activity activity) 方法。

AndroidInjection#inject(Activity activity) 原始碼如下:

  public static void inject(Activity activity) {
    checkNotNull(activity, "activity");
    Application application = activity.getApplication();
    //判斷 Application 是否實現了 HasActivityInjector 介面
    if (!(application instanceof HasActivityInjector)) {
      throw new RuntimeException(
          String.format(
              "%s does not implement %s",
              application.getClass().getCanonicalName(),
              HasActivityInjector.class.getCanonicalName()));
    }

    //從 Application 中獲取 AndroidInjector 物件,即 DispatchingAndroidInjector<Activity> mActivityInjector
    AndroidInjector<Activity> activityInjector =
        ((HasActivityInjector) application).activityInjector();
    checkNotNull(
        activityInjector,
        "%s.activityInjector() returned null",
        application.getClass().getCanonicalName());

    //最後注入到 MainActivity 中,此處是在 Dagger 編譯生成的 DaggerAppComponent.MainActivitySubcomponentImpl 類中實現的。
    activityInjector.inject(activity);
  }複製程式碼

3.2 Fragment 依賴注入(第二種注入方式)

Fragment 使用的是v4相容包中的 android.support.v4.app.Fragment

3.2.1 @Subcomponent

由於在 Activity 依賴注入的第一步已經新增 AndroidInjectionModule,所以這裡可以直接使用。這種方式其實是第一種方式的簡化,如果 MainFragmentSubcomponentMainFragmentSubcomponent.Builder 沒有其他的方法或超型別,如下,

MainFragmentSubcomponent

  @FragmentScope
  @Subcomponent
  public interface MainFragmentSubcomponent extends AndroidInjector<MainFragment> {
      @Subcomponent.Builder
      abstract class Builder extends AndroidInjector.Builder<MainFragment> {
      }
  }複製程式碼

這時可以省略 MainFragmentSubcomponent,也就是說,可以直接不用定義 MainFragmentSubcomponent

3.2.2 @Module

當 Subcomponent 和 它的 Builder 沒有其它方法或超型別時,可以不再需要 Subcomponent。
其實Subcomponent 的作用就是生成 AndroidInjector,而 @ContributesAndroidInjector 註解也可以為我們做這個事情。

MainFragmentModule

  @Module
  public abstract class MainFragmentModule {
      /**
       * 第二種注入方式。當 Subcomponent 和 它的 Builder 沒有其它方法或超型別時,可以不再需要 Subcomponent
       */
      @FragmentScope
      @ContributesAndroidInjector(modules = JordonModule.class)//DataModule
      abstract MainFragment contributeMainFragment();
  }複製程式碼

一些需要注入的資料型別可以包含在 @ContributesAndroidInjector(modules = {}) 中。

MainFragmentModule 裝載到 AppComponent 中:

  @Singleton
  @Component(modules = {AndroidInjectionModule.class,
          MainActivityModule.class,
          MainFragmentModule.class})
  public interface AppComponent {
      void inject(MainApp mainApp);
  }複製程式碼

3.2.3 HasSupportFragmentInjector

讓要依賴注入的目標 Fragment(即 MainFragment) 的宿主 Activity(即 MainActivity) 實現 HasSupportFragmentInjector 介面。
為 Fragment 提供 AndroidInjector,這是 AndroidInjection.inject(Fragment fragment) 所需要的,具體見 3.2.5 的原始碼解析。

MainActivity

  public class MainActivity extends AppCompatActivity implements HasSupportFragmentInjector {
    @Inject
    DispatchingAndroidInjector<Fragment> mFragmentInjector;
    //...

    public void onCreate(Bundle savedInstanceState) {
      AndroidInjection.inject(this);
      super.onCreate(savedInstanceState);
    }

    @Override
    public AndroidInjector<Fragment> supportFragmentInjector() {
        return this.mFragmentInjector;
    }
  }複製程式碼

如果使用 android.app.Fragment,Activity 應該實現 HasFragmentInjector 介面,並注入 DispatchingAndroidInjector
這一步也可以在 Application 實現 HasSupportFragmentInjector 介面,類似 3.1.4 所述。

3.2.4 AndroidInjection

最後,在目標 Fragment 的 onAttach() 方法中進行注入。

MainFragment

  public class MainFragment extends Fragment {
    @Inject
    Person mJordon;//依賴注入

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        AndroidSupportInjection.inject(this);
    }

    //...
  }複製程式碼

3.2.5 原始碼解析

Fragment 注入的原理與 Activity 的類似,這裡再強調一遍,其實第二種方式是第一種方式的簡化,使用 @ContributesAndroidInjector 註解來自動生成 Subcomponent

AndroidSupportInjection#inject(Fragment fragment) 原始碼如下:

  public static void inject(Fragment fragment) {
    checkNotNull(fragment, "fragment");
    //獲取 HasSupportFragmentInjector
    HasSupportFragmentInjector hasSupportFragmentInjector = findHasFragmentInjector(fragment);
    Log.d(
        TAG,
        String.format(
            "An injector for %s was found in %s",
            fragment.getClass().getCanonicalName(),
            hasSupportFragmentInjector.getClass().getCanonicalName()));
    //從 Activity 中獲取 HasSupportFragmentInjector 物件,即 DispatchingAndroidInjector<Fragment> mFragmentInjector
    AndroidInjector<Fragment> fragmentInjector =
        hasSupportFragmentInjector.supportFragmentInjector();
    checkNotNull(
        fragmentInjector,
        "%s.supportFragmentInjector() returned null",
        hasSupportFragmentInjector.getClass().getCanonicalName());
    //最後注入到 MainFragment 中,此處是在 Dagger 編譯生成的 DaggerAppComponent.MainFragmentSubcomponentImpl 類中實現的。
    fragmentInjector.inject(fragment);
  }複製程式碼

AndroidSupportInjection#findHasFragmentInjector(Fragment fragment)

  private static HasSupportFragmentInjector findHasFragmentInjector(Fragment fragment) {
      Fragment parentFragment = fragment;
      while ((parentFragment = parentFragment.getParentFragment()) != null) {
        if (parentFragment instanceof HasSupportFragmentInjector) {
          return (HasSupportFragmentInjector) parentFragment;
        }
      }
      Activity activity = fragment.getActivity();
      if (activity instanceof HasSupportFragmentInjector) {
        return (HasSupportFragmentInjector) activity;
      }
      if (activity.getApplication() instanceof HasSupportFragmentInjector) {
        return (HasSupportFragmentInjector) activity.getApplication();
      }
      throw new IllegalArgumentException(
          String.format("No injector was found for %s", fragment.getClass().getCanonicalName()));
    }複製程式碼

由原始碼可知,如果需要在 Fragment 中進行依賴注入,可以有兩種實現方式:一種是宿主 Activity 實現 HasSupportFragmentInjector,另一種是 Application 實現 HasSupportFragmentInjector。

3.3 其他元件

ServiceBroadcastReceiverContentProvider 的注入方式與此類似。
為了方便,Dagger.Android 為我們提供了一些封裝好的元件類,下面引用官方文件的一段話,如果有需要,可以直接使用這些元件類。

Because DispatchingAndroidInjector looks up the appropriate AndroidInjector.Factory by the class at runtime, a base class can implement HasActivityInjector/HasFragmentInjector/etc as well as call AndroidInjection.inject(). All each subclass needs to do is bind a corresponding @Subcomponent. Dagger provides a few base types that do this, such as DaggerActivity and DaggerFragment, if you don’t have a complicated class hierarchy. Dagger also provides a DaggerApplication for the same purpose — all you need to do is to extend it and override the applicationInjector() method to return the component that should inject the Application.

The following types are also included:

Note: DaggerBroadcastReceiver should only be used when the BroadcastReceiver is registered in the AndroidManifest.xml. When the BroadcastReceiver is created in your own code, prefer constructor injection instead.

4 多 Module 實戰

上面只是簡單的介紹了Dagger.Android 的使用,下面重點來了,還是將通過一個例子,詳解怎麼利用 Dagger 構建多 Module 依賴關係,從而實現元件化。
這裡,將上述對 Activity 和 Fragment 的依賴注入分離到一個 Library Module 中,利用 Application.ActivityLifecycleCallbacksFragmentManager.FragmentLifecycleCallbacks 監聽,構建全域性的依賴注入。

這裡提前提一下本方案下,Dagger 的依賴關係:
DaggerComponent -> AppComponent -> MainActivitySubcomponent/MainFragmentSubcomponent
其中:DaggerComponent 為 library 的注入器,它的作用域是 @Singleton
AppComponent 為主 Module 的全域性注入器,它的作用域是 @AppScope,並且 AppComponent 是依賴於 DaggerComponent,也就是說,DaggerComponent 頂級注入器,AppComponent 是主 Module 的注入器;
MainActivitySubcomponent/MainFragmentSubcomponent 是 Activity/Fragment 的注入器,作用域為 @ActivityScope/@FragmentScope,這裡是 @Subcomponent,通過繼承的方式實現層級依賴,為 AppComponent 的下一級。

AppScope

  @Scope
  @Retention(RUNTIME)
  public @interface AppScope {
  }複製程式碼

4.1 Library Module

4.1.1 DaggerFragmentLifecycleCallbacks - 全域性 Fragment 依賴注入

這裡使用 FragmentLifecycleCallbacks 全域性監聽 Fragment 的生命週期,對 Dagger.Android 進行統一注入管理。

DaggerFragmentLifecycleCallbacks

  public class DaggerFragmentLifecycleCallbacks extends FragmentManager.FragmentLifecycleCallbacks {

      @Inject
      public DaggerFragmentLifecycleCallbacks() {
      }

      @Override
      public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) {
          super.onFragmentAttached(fm, f, context);
          Timber.i(f.toString() + " ---> onFragmentAttached");
          AndroidSupportInjection.inject(f);//Dagger.Android Inject for Fragment
      }

      @Override
      public void onFragmentActivityCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
          super.onFragmentActivityCreated(fm, f, savedInstanceState);
          Timber.i(f.toString() + " ---> onFragmentActivityCreated");
      }

      @Override
      public void onFragmentDetached(FragmentManager fm, Fragment f) {
          super.onFragmentDetached(fm, f);
          Timber.i(f.toString() + " ---> onFragmentDetached");
      }

  }複製程式碼

可以看到,DaggerFragmentLifecycleCallbacks 也是通過 Dagger 進行管理的,在 onFragmentAttached() 方法中進行 Fragment 的依賴注入;並且使用 Timber 列印了幾個關鍵生命週期回撥Log。

4.1.2 DaggerActivityLifecycleCallbacks - 全域性 Activity 依賴注入

這裡使用 ActivityLifecycleCallbacks 全域性監聽 Activity 的生命週期,對 Dagger.Android 進行統一注入管理。

DaggerActivityLifecycleCallbacks

  public class DaggerActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
      @Inject
      DaggerFragmentLifecycleCallbacks mFragmentLifecycleCallbacks;

      @Inject
      public DaggerActivityLifecycleCallbacks() {
      }

      @Override
      public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
          Timber.w(activity + " ---> onActivityCreated");
          AndroidInjection.inject(activity);//Dagger.Android Inject for Activity
          if ((activity instanceof HasSupportFragmentInjector || activity.getApplication() instanceof HasSupportFragmentInjector)
                  && activity instanceof FragmentActivity) {
              ((FragmentActivity) activity).getSupportFragmentManager()
                      .registerFragmentLifecycleCallbacks(mFragmentLifecycleCallbacks, true);
          }
      }

      @Override
      public void onActivityStarted(Activity activity) {

      }

      @Override
      public void onActivityResumed(Activity activity) {

      }

      @Override
      public void onActivityPaused(Activity activity) {

      }

      @Override
      public void onActivityStopped(Activity activity) {

      }

      @Override
      public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

      }

      @Override
      public void onActivityDestroyed(Activity activity) {
          Timber.w(activity + " ---> onActivityDestroyed");
      }
  }複製程式碼

4.1.3 DaggerComponent - 頂級注入器

DaggerComponent

  @Singleton
  @Component(modules = {AndroidInjectionModule.class,
          DaggerModule.class})
  public interface DaggerComponent {
      Application application();

      void inject(DaggerDelegate daggerDelegate);
  }複製程式碼

其中 DaggerModule 主要提供一些全域性依賴,這裡只有一個 provideApplication() 方法,可以自行新增需要的東西。

DaggerModule

  @Module
  public class DaggerModule {
      private final Application mApplication;

      public DaggerModule(Application application) {
          mApplication = application;
      }

      @Singleton
      @Provides
      public Application provideApplication() {
          return this.mApplication;
      }
  }複製程式碼

4.1.4 DaggerDelegate - 開始注入

DaggerDelegate

  public class DaggerDelegate {
      @Inject
      DaggerActivityLifecycleCallbacks mActivityLifecycleCallbacks;

      private DaggerComponent mComponent;
      private final Application mApplication;

      public DaggerDelegate(Application application) {
          mApplication = application;
      }

      public void onCreate() {
          Timber.plant(new Timber.DebugTree());

          mComponent = DaggerDaggerComponent.builder()
                  .daggerModule(new DaggerModule(mApplication))
                  .build();
          mComponent.inject(this);

          mApplication.registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks);
      }


      public DaggerComponent getComponent() {
          return mComponent;
      }
  }複製程式碼

這裡的 DaggerDelegate 是一個代理類,為了克服 Application 繼承的問題,通過封裝一個代理類來對 library 的 Dagger 注入進行管理,然後在需要的 Module 裡使用。

至此,Library Module 的依賴注入結構搭建完成。

4.2 App Module

由上一大節可知,Library Module 中是沒有 Application 的,它是一個 library,如果想使用它,需要在 主 Module 中進行依賴。再說一遍,DaggerComponent 是頂級注入器,AppComponent 主 Module 的全域性注入器,它僅限定於 @AppScope
首先在 app/build.gradle 中新增上節中的 Library Module 依賴:

dependencies {
    //library
    implementation project(':library')

    //...
}複製程式碼

4.2.1 AppComponent - 主 Module 的全域性注入器

AppComponent

  @AppScope
  @Component(dependencies = DaggerComponent.class,
          modules = {AppModule.class,
                  MainActivityModule.class,
                  MainFragmentModule.class})
  public interface AppComponent {
      void inject(MainApp mainApp);
  }複製程式碼

可以看到,dependencies = DaggerComponent.class,這就是上文所說的:AppComponent 是依賴於 DaggerComponent,也就是說,DaggerComponent 頂級注入器,AppComponent 是主 Module 的注入器
其中,AppModule 主要提供主 Module 的一些全域性依賴,可自行擴充套件。

AppModule

  @Module
  public class AppModule {
      private Application mApplication;

      public AppModule(Application application) {
          mApplication = application;
      }
  }複製程式碼

4.2.2 MainApp - 真正注入的地方

MainApp

  public class MainApp extends Application implements HasActivityInjector {
      @Inject
      DispatchingAndroidInjector<Activity> mActivityInjector;

      private DaggerDelegate mDaggerDelegate;
      private AppComponent mAppComponent;

      @Override
      public void onCreate() {
          super.onCreate();

          //Library 的依賴注入(頂級)
          mDaggerDelegate = new DaggerDelegate(this);
          mDaggerDelegate.onCreate();

          //注入主 Module 中(該 Module 全域性)
          mAppComponent = DaggerAppComponent.builder()
                  .daggerComponent(getDaggerComponent())
                  .build();
          mAppComponent.inject(this);

      }

      public DaggerComponent getDaggerComponent() {
          return mDaggerDelegate.getComponent();
      }

      public AppComponent getAppComponent() {
          return mAppComponent;
      }

      @Override
      public AndroidInjector<Activity> activityInjector() {
          return mActivityInjector;
      }
  }複製程式碼

MainApp 是真正進行依賴注入的地方,首先使用上一節 Library Module 中的 DaggerDelegate 進行頂級依賴注入,然後進行 主Module 的依賴注入。需要注意的是,MainApp 必須實現 HasActivityInjector 介面,才能進行 Dagger.Android 注入。

最後不要忘記在 AndroidManifest.xml 中指定 MainApp

4.2.3 MainActivityModule/MainFragmentModule

由第一節的例子可知:當 Subcomponent 和 它的 Builder 沒有其它方法或超型別時,可以不再需要手寫 Subcomponent,而是通過 @ContributesAndroidInjector 註解來自動生成。
所以,這裡的 MainActivitySubcomponent/MainFragmentSubcomponent 可以省略;這樣,MainActivityModule/MainFragmentModule 如下:

MainActivityModule

  @Module
  public abstract class MainActivityModule {
    @ActivityScope
    @ContributesAndroidInjector(modules = KobeModule.class)//DataModule
    abstract MainActivity contributeMainActivity();
  }複製程式碼

MainFragmentModule

  @Module
  public abstract class MainFragmentModule {
      @FragmentScope
      @ContributesAndroidInjector(modules = JordonModule.class)//DataModule
      abstract MainFragment contributeMainFragment();
  }複製程式碼

KobeModule 和 JordonModule 依舊是第一大節中的,就不再重複貼程式碼了。至此就可以在 Activity/Fragment 中進行依賴注入了。Dagger.Adnroid 注入是在 Library Module 中的 DaggerActivityLifecycleCallbacks/DaggerFragmentLifecycleCallbacks 完成的,這是一個全域性監聽器,使用 DaggerDelegateMainApp 中進行註冊的。

4.2.4 總結

再來強調一下,本方案的 Dagger 層級依賴關係:

DaggerComponent -> AppComponent -> MainActivitySubcomponent/MainFragmentSubcomponent
其中:DaggerComponent 為 library 的注入器,它的作用域是 @Singleton
AppComponent 為主 Module 的全域性注入器,它的作用域是 @AppScope,並且 AppComponent 是依賴於 DaggerComponent,也就是說,DaggerComponent 頂級注入器,AppComponent 是主 Module 的注入器;
MainActivitySubcomponent/MainFragmentSubcomponent 是 Activity/Fragment 的注入器,作用域為 @ActivityScope/@FragmentScope,這裡是 @Subcomponent,通過繼承的方式實現層級依賴,為 AppComponent 的下一級。

5 總結

上面兩個例子,第一個介紹了 Dagger.Android 的簡單使用,這是 Dagger2.11 的新姿勢;這樣不需要每個 Activity/Fragment 中再重複手寫一串的依賴注入程式碼;而是通過實現 HasActivityInjector/HasSupportFragmentInjector 介面,通過生命週期的監聽,使用 AndroidInjection.inject() 自動注入。
以上是 MVVMArms 框架的基本的 Dagger 層級依賴關係,更詳細的使用可以檢視 MVVMArms
如果各位有任何疑問,歡迎交流。如果文中有不正之處,也請不吝賜教。
知識分享才會有快樂,後面我會繼續分解 MVVMArms 的關鍵模組,如果各位對 MVVMArms 有任何問題或建議,歡迎一起交流。

6 Github

以上方案的原始碼都可以在 Github 檢視。

7 相關資源

  1. Dagger 2
  2. Dagger & Android
  3. Dagger2 學習

聯絡

我是 xiaobailong24,您可以通過以下平臺找到我:

相關文章