我的Github:https://github.com/BzCoder
本文基于MVPArms進行分析:https://github.com/JessYanCoding/MVPArms
歡迎各位留言討論
Dagger2算是本框架中學(xué)習(xí)成本最高的第三方組件,很多細節(jié)也確實很難在本文章中一言盡之,本文只是單純整理本人在組件化開發(fā)中對于Dagger2的理解與使用。
Dagger2
Dagger2是一個依賴注入框架,什么是依賴注入?簡單通俗的說,將類的初始化通過注入的方式去實現(xiàn)從而降低類與類之間的耦合度。
常用注釋以及含義:
注解 | 含義 |
---|---|
@Inject | 注入 |
@Binds | 指定接口的實現(xiàn) |
@Provides | 提供實例 |
@Named | 類型一致時,需要用Named來指定Inject與Provides 的關(guān)系 |
@Singleton | 單例 |
@Component.Builder | Component的構(gòu)造方法,詳細規(guī)則見Dagger2源代碼中有關(guān)于@Component.Builder注釋 |
@BindsInstance | 為變量先提前打樁 |
組件化項目中使用Dagger2
在組件化工程中雖然分為多個模塊,但是組件之中還是存在諸多共用組件(網(wǎng)絡(luò),緩存,圖片加載,生命周期管理,錯誤管理等),我們保持這些組件的單例,但是同時我們也要保證模塊的低耦合性。此時我們就需要靈活使用Dagger2來解決這些問題。
實現(xiàn)方案
設(shè)定一個父類AppComponent。然后我們工程中所有Component都要通過dependencies依賴此Component以便所有組件可以使用全局共用組件。一般在業(yè)務(wù)頁面(Fragment,Activity)中可以這樣按以下使用。
@xxxxxScope
@Component(modules = xxxxFragmentModule.class, dependencies = AppComponent.class)
public interface xxxxxFragmentComponent {
void inject(xxxxFragment fragment);
@Component.Builder
interface Builder {
@BindsInstance
xxxxtComponent.Builder view(NewsListContract.View view);
xxxxComponent.Builder appComponent(AppComponent appComponent);
xxxxComponent build();
}
}
其中AppComponent關(guān)聯(lián)了三個Module,對應(yīng)了三大塊實例。
1.AppModule
AppModule是App基礎(chǔ)實例,包含了每個模塊都需要的實例以及Application,Activity,F(xiàn)ragment的管理, 其中還包含了我們之前在從零開始Android組件化改造(四) - 模塊配置的統(tǒng)一管理中提到的ActivityLifecycle
。除此之外還包含:
- Gson
- Cache
- ActivityLifecycleCallbacks
- FragmentLifecycleCallbacks
- RepositoryManager
2.ClientModule
ClientModule是第三方框架實例,但是與AppModule不同的是,ClientModule的@Provides方法還包含了第三方的框架配置參數(shù)信息,這些參數(shù)方便在各個模塊中對第三方框架進行個性化配置,而這些信息是通過GlobalConfigModule傳入的,當(dāng)然可以根據(jù)實際情況增減,現(xiàn)在第三方主要包含了以下:
- OkHttpClient
- Retrofit
- RxCache
- RxErrorHandler
- Interceptor
以下代碼為RxCache的注入,其他第三方組件寫法也類似。方法中包含RxCacheConfiguration接口,也就是RxCache的配置信息,這些信息需要在下面的GlobalConfigModule中取得,通過 configuration.configRxCache(application, builder);對RxCache進行配置。
@Singleton
@Provides
static RxCache provideRxCache(Application application, @Nullable RxCacheConfiguration configuration
, @Named("RxCacheDirectory") File cacheDirectory, Gson gson) {
RxCache.Builder builder = new RxCache.Builder();
RxCache rxCache = null;
if (configuration != null) {
rxCache = configuration.configRxCache(application, builder);
}
if (rxCache != null) return rxCache;
return builder
.persistence(cacheDirectory, new GsonSpeaker(gson));
}
3.GlobalConfigModule
GlobalConfigModule是包含配置信息的Module,利用建造者模式+Dagger2構(gòu)建的一個類,通過從零開始Android組件化改造(四) - 模塊配置的統(tǒng)一管理中收集的ConfigModule
將配置收集后,在appDelegate中注入到GlobalConfigModule的Builder中,通過此將所有配置集中到Dagger2中管理,最終通過ClientModule配置到第三方框架中。具體代碼可以在GlobalConfigModule.java查閱。通過
Mainifest->ConfigModule->AppDelegate->GloablConfigModule->ClientModule的路徑,完成各個模塊對于總體工程的配置。
至此我們就介紹完了Dagger2在組件化開發(fā)中使用,其中利用Dagger2完成對于不同模塊對于APP總體配置的實現(xiàn)思路是非常巧妙的。既保證了單一性也保證了靈活性。
4.Dagger2在組件化開發(fā)中遇到的坑
在實際開發(fā)中有這么一個情境,A模塊和B模塊都繼承一個公用abstract BaseFragment,如果不在公用模塊將其實例化的話,就會報XX_MembersInjector.class is repeatedly generated in the wrong package的錯誤,原因是Dagger2會在每個模塊中重新生成一個BaseFragment_MembersInjector.class從而導(dǎo)致類的重復(fù)。解決的方法是在公共模塊寫一個該類的空實現(xiàn)即可解決。在Dagger2的GitHun的issue中也同樣有人提出了這個問題:https://github.com/google/dagger/issues/955。