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

前言

成爲一名優秀的Android開發,須要一份完備的知識體系,在這裏,讓咱們一塊兒成長爲本身所想的那樣~。

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

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

1、預備知識

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

一、@Inject

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

獲取所需依賴:

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

提供所需實例:

  • 構造器注入(若是有多個構造函數,只能註解一個,不然編譯報錯)

二、@Module

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

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

三、@Singleton

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

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

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

四、@Providers

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

注意:源碼分析

  • 使用了@Providers的方法應使用provide做爲前綴,使用了@Module的類應使用Module做爲後綴。
  • 若是@Providers方法或@Inject構造方法有參數,要保證它可以被dagger獲取到,好比經過其它@Providers方法或者@Inject註解構造器的形式獲得

五、@Component

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

Component與Module的區別:

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

六、@Scope

註解做用域,經過自定義註解限定對象做用範圍,加強可讀性

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

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

七、@Qualifier

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

八、dependencies

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

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

九、@SubComponent

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

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

2、簡單示例(取自AwesomeWanAndroid

一、首先,建立一個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)。

二、而後,建立一個將會導入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維護

三、接着,配置項目的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。

四、最後,將目標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;
    }

    ...
    
}
複製代碼

從上面的使用流程中,有三個關鍵的核心實現是咱們須要瞭解的,以下所示:

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

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

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

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

3、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的依賴管理機制都是如此。

4、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。

5、在目標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的核心源碼分析就結束了。

5、總結

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

參考連接:

一、Dagger V2.1.5 源碼

二、Android進階之光

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

四、Android Dagger2 從零單排

Contanct Me

● 微信:

歡迎關注個人微信:bcce5360

● 微信羣:

微信羣若是不能掃碼加入,麻煩你們想進微信羣的朋友們,加我微信拉你進羣。

● QQ羣:

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

About me

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

但願咱們能成爲朋友,在 Github掘金上一塊兒分享知識。

相關文章
相關標籤/搜索