組件化的目的是爲了業務解耦,每一個業務模塊須要不一樣的功能,例如車輛詳情模塊須要第三方分享,城市定位模塊須要百度地位等。有些特殊功能的初始化須要在 Application 中去作,可是這些功能並不是所有業務組件都用到的東西,放到 BaseApplication 不合適。android
所以,我想這樣操做:git
設想是美好的,但實現前須要先思考一個問題:github
多 Module 項目開發的時候,app module 和 library module 的 都有不一樣的自定義 Application ,能夠共存而且自動合併嗎?bash
答案是 No。微信
首先,自定義 Application 須要聲明在 AndroidManifest.xml 中。其次,每一個 Module 都有該清單文件,可是最終的 APK 文件只能包含一個。所以,在構建應用時,Gradle 構建會將全部清單文件合併到一個封裝到 APK 的清單文件中。app
合併的優先級是:ide
App Module > Library Module工具
合併的規則:組件化
結合咱們的狀況,是值 A 合併值 B,會產生衝突錯誤,以下是個人親身試法:post
Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : Attribute application@name value=(com.baseres.BaseApplication) from AndroidManifest.xml:8:9-51
is also present at [:carcomponent] AndroidManifest.xml:14:9-55 value=(com.carcomponent.CarApplication).
Suggestion: add 'tools:replace="android:name"' to <application> element at AndroidManifest.xml:7:5-24:19 to override.
複製代碼
錯誤信息中給出瞭解決建議,在高優先級的 App Module 中使用 tools:replace="android:name",但這樣作是直接用值 A 替換了值 B,並不是咱們想要的結果。
除了上面報錯的方法,另外再推薦給你們一個方法,打開 App Module 的 AndroidManifest.xml 文件,選擇下方 Merged Manifest 選項卡,能夠看到預合併結果。
以上咱們就明白爲何不一樣的 Application 不能共存的緣由。那還有其餘方法去實現美好設想嗎?
此次的答案是 Yes !
回想需求來源,是須要在 Application 建立時期,實現模塊的特殊功能初始化,初始化時間和初始化內容 是肯定無誤,問題核心是如何鏈接二者。直接鏈接方式實踐失敗,只能採用間接方式。一提到間接,因而想起來了反射。
以上就已經解決咱們的問題,可是爲了 A 類 和 B 類 中的初始化方法名稱保持一致,最好使用接口強制規範。建立接口 IComponentApplication,其中定義好方法簽名,讓 A 類和 B 類都實現它。如此,接口應放在 基礎庫 BaseRes 中,反射調用內容放在 BaseApplication 最爲合適。
全部的思惟邏輯演變成代碼是這樣紙的:
Module A:
private class A implements IComponentApplication{
public void init(Application application){
// ModuleA的初始化
}
}
Module B:
private class B implements IComponentApplication{
public void init(Application application){
// ModuleB的初始化
}
}
BaseRes 中:
public interface IComponentApplication {
void init(Application application);
}
public class MyApplication extends Application {
private static final String[] MODULESLIST =
{"com.moduleA.A",
"com.moduleA.B"};
@Override
public void onCreate() {
super.onCreate();
//Module類的APP初始化
modulesApplicationInit();
}
private void modulesApplicationInit(){
for (String moduleImpl : MODULESLIST){
try {
Class<?> clazz = Class.forName(moduleImpl);
Object obj = clazz.newInstance();
if (obj instanceof IComponentApplication){
((IComponentApplication) obj).init(BaseApplication.getInstance());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
}
複製代碼
福利是組件化系列博客所說的方案,寫出來了一個Demo,傳送門在這裏 大家可能須要的組件化 Demo。說是福利,大概是個人臉太大,技術淺薄,歡迎指正和交流。
另外,關於 AndroidManifest.xml 的合併,詳細瞭解能夠看這裏合併多個清單文件 Google 官方文檔,須要自備交通工具。
最後是個人組件化系列文章,內容簡單易懂,但願對你能有所幫助:
下篇文章見。