Android主流三方庫源碼分析(八、深入理解Dagger2源碼)

前言

成爲一名優秀的Android開發,需要一份完備的知識體系,在這裏,讓我們一起成長爲自己所想的那樣~。

上一篇,筆者詳細地分析了Android中的依賴注入框架ButterKnife,使用它幫助我們解決了重複編寫findViewById和setOnclickListener的繁瑣。衆所周知,當項目越來越大時,類之間的調用層次會越來越深,並且有些類是Activity/Fragment,有些是單例,而且它們的生命週期也不是一致的,所以創建這些對象時要處理的各個對象的依賴關係和生命週期時的任務會很繁重,因此,爲了解決這個問題Dagger2應運而生。相比ButterKnife的輕量級使用,Dagger2會顯得更重量級和鋒利一些,它能夠掌控全局,對項目中幾乎所有的依賴進行集成管理。如果有對Binder架構體系比較瞭解的朋友應該知道,其中的服務大管家ServiceManager負責所有的服務(引導服務、核心服務、其它服務)的管理,而Dagger2其實就是將項目中的依賴進行了集成管理。下面,筆者來跟大家一起探索Dagger2的內部實現機制,看看它是如何進行依賴管理的。

Dagger2其實同RxJava一樣,是一種多平臺通用的庫。由於Dagger2的通用寫法比較繁瑣,因此,Google推出了適用於Android平臺的Dagger.Android用法。本文,將基於Dagger.Android的源碼對Dagger2內部的實現機制進行探索。

一、預備知識

鑑於Dagger有一定的上手成本,這裏首先帶大家複習一下本篇源碼分析可能會涉及到的相關基礎知識點,以此降低閱讀難度。

1、@Inject

告訴dagger這個字段或類需要依賴注入,然後在需要依賴的地方使用這個註解,dagger會自動生成這個構造器的實例。

獲取所需依賴:

  • 全局變量注入
  • 方法注入

提供所需實例:

  • 構造器注入(如果有多個構造函數,只能註解一個,否則編譯報錯)

2、@Module

類註解,表示此類的方法是提供依賴的,它告訴dagger在哪可以找到依賴。用於不能用@Inject提供依賴的地方,如第三方庫提供的類,基本數據類型等不能修改源碼的情況。

注意:Dagger2會優先在@Module註解的類上查找依賴,沒有的情況纔會去查詢類的@Inject構造方法

3、@Singleton

聲明這是一個單例,在確保只有一個Component並且不再重新build()之後,對象只會被初始化一次,之後的每次都會被注入相同的對象,它就是一個內置的作用域。

對於@Singleton,大家可能會產生一些誤解,這裏詳細闡述下:

  • Singleton容易給人造成一種誤解就是用Singleton註解後在整個Java代碼中都是單例,但實際上他和Scope一樣,只是在同一個Component是單例。也就是說,如果重新調用了component的build()方法,即使使用了Singleton註解了,但仍然獲取的是不同的對象。
  • 它表明了**@Singleton註解只是聲明瞭這是一個單例,爲的只是提高代碼可讀性,其實真正控制對象生命週期的還是Component**。同理,自定義的@ActivityScope 、@ApplicationScope也僅僅是一個聲明的作用,真正控制對象生命週期的還是Component

4、@Providers

只在@Module中使用,用於提供構造好的實例。一般與@Singleton搭配,用單例方法的形式對外提供依賴,是一種替代@Inject註解構造方法的方式。

注意:

  • 使用了@Providers的方法應使用provide作爲前綴,使用了@Module的類應使用Module作爲後綴。
  • 如果@Providers方法或@Inject構造方法有參數,要保證它能夠被dagger獲取到,比如通過其它@Providers方法或者@Inject註解構造器的形式得到

5、@Component

@Component作爲Dagger2的容器總管,它擁有着@Inject與@Module的所有依賴。同時,它也是一枚注射器,用於獲取所需依賴和提供所需依賴的橋樑。這裏的橋樑即指@Inject和@Module(或@Inject構造方法)之間的橋樑。定義時需要列出響應的Module組成,此外,還可以使用dependencies繼承父Component。

Component與Module的區別:

Component既是注射器也是一個容器總管,而module則是作爲容器總管Component的子容器,實質是一個用於提供依賴的模塊。

6、@Scope

註解作用域,通過自定義註解限定對象作用範圍,增強可讀性

@Scope有兩種常用的使用場景:

  • 模擬Singleton代表全局單例,與Component生命週期關聯
  • 模擬局部單例,如登錄到退出登錄期間

7、@Qualifier

限定符,利用它定義註解類以用於區分類的不同實例。例如:2個方法返回不同的Person對象,比如說小明和小華,爲了區分,使用@Qualifier定義的註解類。

8、dependencies

使用它表示ChildComponent依賴於FatherComponent,如下所示:

@Component(modules = ChildModule.class, dependencies = FatherComponent.class)
public interface ChildComponent {
    ...
}

9、@SubComponent

表示是一個子@Component,它能將應用的不同部分封裝起來,用來替代@Dependencies

回顧完Dagger2的基礎知識,下面我們要啓動發動機了。

二、簡單示例(取自AwesomeWanAndroid

1、首先,創建一個BaseActivityComponent的Subcomponent:

@Subcomponent(modules = {AndroidInjectionModule.class})
public interface BaseActivityComponent extends AndroidInjector<BaseActivity> {

    @Subcomponent.Builder
    abstract class BaseBuilder extends AndroidInjector.Builder<BaseActivity>{
    }
}

這裏必須要註解成@Subcomponent.Builder表示是頂級@Subcomponent的內部類。AndroidInjector.Builder的泛型指定了BaseActivity,即表示每一個繼承於BaseActivity的Activity都繼承於同一個子組件(BaseActivityComponent)。

2、然後,創建一個將會導入Subcomponent的公有Module。

// 1
@Module(subcomponents = {BaseActivityComponent.class})
public abstract class AbstractAllActivityModule {

    @ContributesAndroidInjector(modules = MainActivityModule.class)
    abstract MainActivity contributesMainActivityInjector();

    @ContributesAndroidInjector(modules = SplashActivityModule.class)
    abstract SplashActivity contributesSplashActivityInjector();
    
    // 一系列的對應Activity的contributesxxxActivityInjector
    ...
    
}

在註釋1處用subcomponents來表示開放全部依賴給AbstractAllActivityModule,使用Subcomponent的重要原因是它將應用的不同部分封裝起來了。@AppComponent負責維護共享的數據和對象,而不同處則由各自的@Subcomponent維護

3、接着,配置項目的Application。

public class WanAndroidApp extends Application implements HasActivityInjector {

    // 3
    @Inject
    DispatchingAndroidInjector<Activity> mAndroidInjector;

    private static volatile AppComponent appComponent;
    
    @Override
    public void onCreate() {
        super.onCreate();
        
        ...
        // 1
        appComponent = DaggerAppComponent.builder()
            .build();
        // 2
        appComponent.inject(this);
        
        ...
        
    }
    
    ...
    
    // 4
    @Override
    public AndroidInjector<Activity> activityInjector() {
        return mAndroidInjector;
    }
}

首先,在註釋1處,使用AppModule模塊和httpModule模塊構建出AppComponent的實現類DaggerAppComponent。這裏看一下AppComponent的配置代碼:

@Singleton
@Component(modules = {AndroidInjectionModule.class,
        AndroidSupportInjectionModule.class,
        AbstractAllActivityModule.class,
        AbstractAllFragmentModule.class,
        AbstractAllDialogFragmentModule.class}
    )
public interface AppComponent {

    /**
     * 注入WanAndroidApp實例
     *
     * @param wanAndroidApp WanAndroidApp
     */
    void inject(WanAndroidApp wanAndroidApp);
    
    ...
    
}

可以看到,AppComponent依賴了AndroidInjectionModule模塊,它包含了一些基礎配置的綁定設置,如activityInjectorFactories、fragmentInjectorFactories等等,而AndroidSupportInjectionModule模塊顯然就是多了一個supportFragmentInjectorFactories的綁定設置,activityInjectorFactories的內容如所示:

@Beta
@Module
public abstract class AndroidInjectionModule {
    @Multibinds
    abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>>
        activityInjectorFactories();
    
    @Multibinds
    abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>>
        fragmentInjectorFactories();
    
    ...

}

接着,下面依賴的AbstractAllActivityModule、
AbstractAllFragmentModule、AbstractAllDialogFragmentModule則是爲項目的所有Activity、Fragment、DialogFragment提供的統一基類抽象Module,這裏看下AbstractAllActivityModule的配置:

@Module(subcomponents = {BaseActivityComponent.class})
public abstract class AbstractAllActivityModule {

    @ContributesAndroidInjector(modules = MainActivityModule.class)
    abstract MainActivity contributesMainActivityInjector();

    @ContributesAndroidInjector(modules = SplashActivityModule.class)
    abstract SplashActivity contributesSplashActivityInjector();
    
    ...
    
}

可以看到,項目下的所有xxxActiviity都有對應的contributesxxxActivityInjector()方法提供實例注入。並且,注意到AbstractAllActivityModule這個模塊依賴的
subcomponents爲BaseActivityComponent,前面說過了,每一個繼承於BaseActivity的Activity都繼承於BaseActivityComponent這一個subcomponents。同理,AbstractAllFragmentModule與AbstractAllDialogFragmentModule也是類似的實現模式,如下所示:

// 1
@Module(c = BaseFragmentComponent.class)
public abstract class AbstractAllFragmentModule {

    @ContributesAndroidInjector(modules = CollectFragmentModule.class)
    abstract CollectFragment contributesCollectFragmentInject();

    @ContributesAndroidInjector(modules = KnowledgeFragmentModule.class)
    abstract KnowledgeHierarchyFragment contributesKnowledgeHierarchyFragmentInject();
    
    ...
    
}


// 2
@Module(subcomponents = BaseDialogFragmentComponent.class)
public abstract class AbstractAllDialogFragmentModule {

    @ContributesAndroidInjector(modules = SearchDialogFragmentModule.class)
    abstract SearchDialogFragment contributesSearchDialogFragmentInject();

    @ContributesAndroidInjector(modules = UsageDialogFragmentModule.class)
    abstract UsageDialogFragment contributesUsageDialogFragmentInject();

}

注意到註釋1和註釋2處的代碼,AbstractAllFragmentModule和AbstractAllDialogFragmentModule的subcomponents爲BaseFragmentComponent、BaseDialogFragmentComponent,很顯然,同AbstractAllActivityModule的子組件BaseActivityComponent一樣,它們都是作爲一個通用的子組件。

然後,回到我們配置項目下的Application下面的註釋2處的代碼,在這裏使用了第一步Dagger爲我們構建的DaggerAppComponent對象將當期的Application實例注入了進去,交給了Dagger這個依賴大管家去管理。最終,Dagger2內部創建的mAndroidInjector對象會在註釋3處的地方進行實例賦值。在註釋4處,實現HasActivityInjector接口,重寫activityInjector()方法,將我們上面得到的mAndroidInjector對象返回。這裏的mAndroidInjector是一個類型爲DispatchingAndroidInjector的對象,可以這樣理解它:它能夠執行Android框架下的核心成員如Activity、Fragment的成員注入,在我們項目下的Application中將DispatchingAndroidInjector的泛型指定爲Activity就說明它承擔起了所有Activity成員依賴的注入。那麼,如何指定某一個Activity能被納入DispatchingAndroidInjector這個所有Activity的依賴總管的口袋中呢?接着看使用步驟4。

4、最後,將目標Activity納入Activity依賴分配總管DispatchingAndroidInjector的囊中。

很簡單,只需在目標Activity的onCreate()方法前的super.onCreate(savedInstanceState)前配置一行代碼 AndroidInjection.inject(this),如下所示:

public abstract class BaseActivity<T extends AbstractPresenter> extends AbstractSimpleActivity implements
    AbstractView {

    ...
    @Inject
    protected T mPresenter;
    
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
    }

    ...
    
}

這裏使用了@Inject表明了需要注入mPresenter實例,然後,我們需要在具體的Presenter類的構造方法上使用@Inject提供基於當前構造方法的mPresenter實例,如下所示:

public class MainPresenter extends BasePresenter<MainContract.View> implements MainContract.Presenter {

    ...

    @Inject
    MainPresenter(DataManager dataManager) {
        super(dataManager);
        this.mDataManager = dataManager;
    }

    ...
    
}

從上面的使用流程中,有三個關鍵的核心實現是我們需要了解的,如下所示:

  • 1、appComponent = DaggerAppComponent.builder().build()這句代碼如何構建出DaggerAPPComponent的?

  • 2、appComponent.inject(this)是如何將mAndroidInjector實例賦值給當前的Application的?

  • 3、在目標Activity下的AndroidInjection.inject(this)這句代碼是如何將當前Activity對象納入依賴分配總管DispatchingAndroidInjector囊中的呢?

下面,讓我們來逐個一一地來探索其中的奧妙吧~

三、DaggerAppComponent.builder().build()是如何構建出DaggerAPPComponent的?

首先,我們看到DaggerAppComponent的builder()方法:

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

裏面直接返回了一個新建的Builder靜態內部類對象,看看它的構造方法中做了什麼:

public static final class Builder {

    private Builder() {}
    
    ...
    
}

看來,Builder的默認構造方法什麼也沒有做,那麼,真正的實現肯定在Builder對象的build()方法中,接着看到build()方法。

public static final class Builder {

    ...
 
    public AppComponent build() {
         return new DaggerAppComponent(this);
    }

    ...

}

在Builder的build()方法中直接返回了新建的DaggerAppComponent對象。下面,看看DaggerAppComponent的構造方法:

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

在DaggerAppComponent的構造方法中調用了initialize方法,顧名思義,它就是真正初始化項目全局依賴配置的地方了,下面,來看看它內部的實現:

private void initialize(final Builder builder) {
    // 1
    this.mainActivitySubcomponentBuilderProvider =
        new Provider<
            AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
                .Builder>() {
        @Override
        public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
                .Builder
            get() {
                // 2
                return new MainActivitySubcomponentBuilder();
            }
        };

    // 一系列xxxActivitySubcomponentBuilderProvider的創建賦值代碼塊
    ...

}

在註釋1處,新建了一個mainActivit的子組件構造器實例提供者Provider。在註釋2處,使用匿名內部類的方式重寫了該Provider的get()方法,返回一個新創建好的MainActivitySubcomponentBuilder對象。很顯然,它就是負責創建管理MAinActivity中所需依賴的Subcomponent建造者。接下來我們重點來分析下MainActivitySubcomponentBuilder這個類的作用。

// 1
private final class MainActivitySubcomponentBuilder
  extends AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
      .Builder {
    private MainActivity seedInstance;
    
    @Override
    public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
        build() {
      if (seedInstance == null) {
        throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
      }
      // 2
      return new MainActivitySubcomponentImpl(this);
    }
    
    @Override
    public void seedInstance(MainActivity arg0) {
      // 3
      this.seedInstance = Preconditions.checkNotNull(arg0);
    }
}

首先,在註釋1處,MainActivitySubcomponentBuilder繼承了AbstractAllActivityModule_ContributesMainActivityInjector內部的子組件MainActivitySubcomponent的內部的子組件建造者類Builder,如下所示:

@Subcomponent(modules = MainActivityModule.class)
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
    @Subcomponent.Builder
    abstract class Builder extends
    AndroidInjector.Builder<MainActivity> {}
}

可以看到,這個子組件建造者Builder又繼承了AndroidInjector的抽象內部類Builder,那麼,這個AndroidInjector到底是什麼呢?

顧名思義,AndroidInjector是一個Android注射器,它爲每一個具體的子類型,即核心Android類型Activity和Fragment執行成員注入。

接下來我們便來分析下AndroidInjector的內部實現,源碼如下所示:

public interface AndroidInjector<T> {

    void inject(T instance);
    
    // 1
    interface Factory<T> {
        AndroidInjector<T> create(T instance);
    }
    
    // 2
    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();
    }
}

在註釋1處,使用了抽象工廠模式,用來創建一個具體的Activity或Fragment類型的AndroidInjector實例。註釋2處,Builder實現了AndroidInjector.Factory,它是一種Subcomponent.Builder的通用實現模式,在重寫的create()方法中,進行了實例保存seedInstance()和具體Android核心類型的構建。

接着,我們回到MainActivitySubcomponentBuilder類,可以看到,它實現了AndroidInjector.Builder的seedInstance()和build()方法。在註釋3處首先播種了MainActivity的實例,然後
在註釋2處新建了一個MainActivitySubcomponentImpl對象返回。我們看看MainActivitySubcomponentImpl這個類是如何將mPresenter依賴注入的,相關源碼如下:

private final class MainActivitySubcomponentImpl
    implements AbstractAllActivityModule_ContributesMainActivityInjector
    .MainActivitySubcomponent {
      
    private MainPresenter getMainPresenter() {
        // 2
        return MainPresenter_Factory.newMainPresenter(
        DaggerAppComponent.this.provideDataManagerProvider.get());
    }

    @Override
    public void inject(MainActivity arg0) {
        // 1
        injectMainActivity(arg0);
    }

    private MainActivity injectMainActivity(MainActivity instance) {
        // 3
        BaseActivity_MembersInjector
        .injectMPresenter(instance, getMainPresenter());
        return instance;
    }

在註釋1處,MainActivitySubcomponentImpl實現了AndroidInjector接口的inject()方法,在injectMainActivity()首先調用getMainPresenter()方法從MainPresenter_Factory工廠類中新建了一個MainPresenter對象。我們看看MainPresenter的newMainPresenter()方法:

public static MainPresenter newMainPresenter(DataManager dataManager) {
    return new MainPresenter(dataManager);
}

這裏直接新建了一個MainPresenter。然後我們回到MainActivitySubcomponentImpl類的註釋3處,繼續調用了BaseActivity_MembersInjector的injectMPresenter()方法,顧名思義,可以猜到,它是BaseActivity的成員注射器,繼續看看injectMPresenter()內部:

public static <T extends AbstractPresenter> void injectMPresenter(
  BaseActivity<T> instance, T mPresenter) {
    instance.mPresenter = mPresenter;
}

可以看到,這裏直接將需要的mPresenter實例賦值給了BaseActivity的mPresenter,當然,這裏其實是指的BaseActivity的子類MainActivity,其它的xxxActivity的依賴管理機制都是如此。

四、appComponent.inject(this)是如何將mAndroidInjector實例賦值給當前的Application的?

我們繼續查看appComponent的inject()方法:

@Override
public void inject(WanAndroidApp wanAndroidApp) {
  injectWanAndroidApp(wanAndroidApp);
}

在inject()方法裏調用了injectWanAndroidApp(),繼續查看injectWanAndroidApp()方法:

private WanAndroidApp injectWanAndroidApp(WanAndroidApp instance) {
    WanAndroidApp_MembersInjector.injectMAndroidInjector(
        instance,
        getDispatchingAndroidInjectorOfActivity());
    return instance;
}

首先,執行getDispatchingAndroidInjectorOfActivity()方法得到了一個Activity類型的DispatchingAndroidInjector對象,繼續查看getDispatchingAndroidInjectorOfActivity()方法:

private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
    return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
    getMapOfClassOfAndProviderOfFactoryOf());
}

在getDispatchingAndroidInjectorOfActivity()方法裏面,首先調用了getMapOfClassOfAndProviderOfFactoryOf()方法,我們看到這個方法:

private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
  getMapOfClassOfAndProviderOfFactoryOf() {
    return MapBuilder
        .<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
        newMapBuilder(8)
        .put(MainActivity.class, (Provider) mainActivitySubcomponentBuilderProvider)
        .put(SplashActivity.class, (Provider) splashActivitySubcomponentBuilderProvider)
        .put(ArticleDetailActivity.class,
            (Provider) articleDetailActivitySubcomponentBuilderProvider)
        .put(KnowledgeHierarchyDetailActivity.class,
            (Provider) knowledgeHierarchyDetailActivitySubcomponentBuilderProvider)
        .put(LoginActivity.class, (Provider) loginActivitySubcomponentBuilderProvider)
        .put(RegisterActivity.class, (Provider) registerActivitySubcomponentBuilderProvider)
        .put(AboutUsActivity.class, (Provider) aboutUsActivitySubcomponentBuilderProvider)
        .put(SearchListActivity.class, (Provider) searchListActivitySubcomponentBuilderProvider)
        .build();
}

可以看到,這裏新建了一個建造者模式實現的MapBuilder,並且同時制定了固定容量爲8,將項目下使用了AndroidInjection.inject(mActivity)方法的8個Activity對應的xxxActivitySubcomponentBuilderProvider保存起來。

我們再回到getDispatchingAndroidInjectorOfActivity()方法,這裏將上面得到的Map容器傳入了DispatchingAndroidInjector_Factory的newDispatchingAndroidInjector()方法中,這裏應該就是新建DispatchingAndroidInjector的地方了。我們點進去看看:

public static <T> DispatchingAndroidInjector<T> newDispatchingAndroidInjector(
  Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories) {
    return new DispatchingAndroidInjector<T>(injectorFactories);
}

在這裏,果然新建了一個DispatchingAndroidInjector對象。繼續看看DispatchingAndroidInjector的構造方法:

@Inject
DispatchingAndroidInjector(
  Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories) {
    this.injectorFactories = injectorFactories;
}

這裏僅僅是將傳進來的Map容器保存起來了。

我們再回到WanAndroidApp_MembersInjector的injectMAndroidInjector()方法,將上面得到的DispatchingAndroidInjector實例傳入,繼續查看injectMAndroidInjector()這個方法:

public static void injectMAndroidInjector(
  WanAndroidApp instance, DispatchingAndroidInjector<Activity> mAndroidInjector) {
    instance.mAndroidInjector = mAndroidInjector;
}

可以看到,最後在WanAndroidApp_MembersInjector的injectMAndroidInjector()方法中,直接將新建好的DispatchingAndroidInjector實例賦值給了WanAndroidApp的mAndroidInjector。

五、在目標Activity下的AndroidInjection.inject(this)這句代碼是如何將當前Activity對象納入依賴分配總管DispatchingAndroidInjector囊中的呢?

首先,我們看到AndroidInjection.inject(this)這個方法:

public static void inject(Activity activity) {
    checkNotNull(activity, "activity");
    
    // 1
    Application application = activity.getApplication();
    if (!(application instanceof HasActivityInjector)) {
    throw new RuntimeException(
        String.format(
            "%s does not implement %s",
            application.getClass().getCanonicalName(), 
            HasActivityInjector.class.getCanonicalName()));
    }

    // 2
    AndroidInjector<Activity> activityInjector =
        ((HasActivityInjector) application).activityInjector();
        
    checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());

    // 3
    activityInjector.inject(activity);

}

在註釋1處,會先判斷當前的application是否實現了HasActivityInjector這個接口,如果沒有,則拋出RuntimeException。如果有,會繼續在註釋2處調用application的activityInjector()方法得到DispatchingAndroidInjector實例。最後,在註釋3處,會將當前的activity實例傳入activityInjector的inject()方法中。我們繼續查看inject()方法:

@Override
public void inject(T instance) {
    boolean wasInjected = maybeInject(instance);
    if (!wasInjected) {
        throw new IllegalArgumentException(errorMessageSuggestions(instance));
    }
}

DispatchingAndroidInjector的inject()方法,它的作用就是給傳入的instance實例執行成員注入。具體在這個案例中,其實就是負責將創建好的Presenter實例賦值給BaseActivity對象
的mPresenter全局變量。在inject()方法中,又調用了maybeInject()方法,我們繼續查看它:

@CanIgnoreReturnValue
public boolean maybeInject(T instance) {
    // 1
    Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
    injectorFactories.get(instance.getClass());
    if (factoryProvider == null) {
    return false;
    }

    @SuppressWarnings("unchecked")
    // 2
    AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
    try {
        // 3
        AndroidInjector<T> injector =
            checkNotNull(
                factory.create(instance), "%s.create(I) should not return null.", factory.getClass());
        // 4
        injector.inject(instance);
        return true;
    } catch (ClassCastException e) {
        ...
    }
}

在註釋1處,我們從injectorFactories(前面得到的Map容器)中根據當前Activity實例拿到了factoryProvider對象,這裏我們具體一點,看到MainActivity對應的factoryProvider,也就是我們研究的第一個問題中的mainActivitySubcomponentBuilderProvider:

private void initialize(final Builder builder) {
    this.mainActivitySubcomponentBuilderProvider =
        new Provider<
            AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
            .Builder>() {
        @Override
        public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
                .Builder
            get() {
                return new MainActivitySubcomponentBuilder();
            }
        };

    ...
    
}

在maybeInject()方法的註釋2處,調用了mainActivitySubcomponentBuilderProvider的get()方法得到了一個新建的MainActivitySubcomponentBuilder對象。在註釋3處執行了它的create方法,create()方法的具體實現在AndroidInjector的內部類Builder中:

abstract class Builder<T> implements AndroidInjector.Factory<T> {
    @Override
    public final AndroidInjector<T> create(T instance) {
        seedInstance(instance);
        return build();
    }

看到這裏,我相信看過第一個問題的同學已經明白後面是怎麼回事了。在create()方法中,我們首先MainActivitySubcomponentBuilder的seedInstance()將MainActivity實例注入,然後再調用它的build()方法新建了一個MainActivitySubcomponentImpl實例返回。

最後,在註釋4處,執行了MainActivitySubcomponentImpl的inject()方法:

private final class MainActivitySubcomponentImpl
    implements AbstractAllActivityModule_ContributesMainActivityInjector
    .MainActivitySubcomponent {
      
    private MainPresenter getMainPresenter() {
        // 2
        return MainPresenter_Factory.newMainPresenter(
        DaggerAppComponent.this.provideDataManagerProvider.get());
    }

    @Override
    public void inject(MainActivity arg0) {
        // 1
        injectMainActivity(arg0);
    }

    private MainActivity injectMainActivity(MainActivity instance) {
        // 3
        BaseActivity_MembersInjector
        .injectMPresenter(instance, getMainPresenter());
        return instance;
    }

這裏的邏輯已經在問題一的最後部分詳細講解了,最後,會在註釋3處調用BaseActivity_MembersInjector的injectMPresenter()方法:

public static <T extends AbstractPresenter> void injectMPresenter(
  BaseActivity<T> instance, T mPresenter) {
    instance.mPresenter = mPresenter;
}

這樣,就將mPresenter對象賦值給了當前Activity對象的mPresenter全局變量中了。至此,Dagger.Android的核心源碼分析就結束了。

五、總結

相比於ButterKnife,Dagger是一個鋒利的全局依賴注入管理框架,它主要用來管理對象的依賴關係和生命週期,當項目越來越大時,類之間的調用層次會越來越深,並且有些類是Activity或Fragment,有些是單例,而且它們的生命週期不一致,所以創建所需對象時需要處理的各個對象的依賴關係和生命週期時的任務會很繁重。因此,使用Dagger會大大減輕這方面的工作量。雖然它的學習成本比較高,而且需要寫一定的模板類,但是,對於越大的項目來說,Dagger越值得被需要。下一篇,便是Android主流三方庫源碼分析系列的終結篇了,筆者將會對Android中的事件總線框架EventBus源碼進行深入的分析,敬請期待~

參考鏈接:

1、Dagger V2.1.5 源碼

2、Android進階之光

3、告別Dagger2模板代碼:DaggerAndroid原理解析

4、Android Dagger2 從零單排

Contanct Me

● 微信:

歡迎關注我的微信:bcce5360

● 微信羣:

微信羣如果不能掃碼加入,麻煩大家想進微信羣的朋友們,加我微信拉你進羣。

● QQ羣:

2千人QQ羣,Awesome-Android學習交流羣,QQ羣號:959936182, 歡迎大家加入~

About me

很感謝您閱讀這篇文章,希望您能將它分享給您的朋友或技術羣,這對我意義重大。

希望我們能成爲朋友,在 Github掘金上一起分享知識。

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