原文首發於微信公衆號:躬行之(jzman-blog)java
上一篇文章籠統的總結了一下組件化開發的一些基礎性問題,本篇文章繼續組件化的學習,主要分以下三個方面介紹組件化中的 Application 以下:android
Androuid 應用的啓動的時候最早啓動的就是 Application,每一個 App 運行時僅建立惟一一個 Application,其生命週期就是 App 的生命週期,Application 中經常使用的回調方法以下:微信
其中附上一張來自Carson_Ho總結的 onTrimMemory 相關內存級別的說明以下:app
Application 做爲整個 App 的一個單例對象,其做用以下:ide
AndroidManifest 是每一個 Module 的聲明配置文件,對應的在生成一個 App 的時候也應該對應一份 AndroidManifest 文件,那麼在多個 Module 彼此依賴的狀況下就須要合併子 Module 的 AndroidManifest 文件內容到主 Module 的 AndroidManifest 文件中,最終會在 build 目錄下 生成最終的 AndroidManifest 文件,編譯生成的 AndroidManifest 文件的具體路徑參考以下:組件化
app\build\intermediates\manifests\full\debug\AndroidManifest.xml
複製代碼
在合併子 Modulen 的 AndroidManifest 文件時,編譯器會補全 use-sdk 的信息以及一些未設置的屬性,在合併後如 Activity 等組件中的 name 屬性都以包名+文件名來指定。post
其中在合併 AndroidManifest 文件要對 Application 進行合併, Application 合併規則以下:性能
在合併過程當中若是不添加 tools:replace 屬性,則會提示添加 tools:android 屬性,提示的錯誤信息以下:學習
Manifest merger failed : Attribute application@name value=(com.manu.module_one.OneApplication) from [:moduel_one] AndroidManifest.xml:13:9-58
is also present at [:module_two] AndroidManifest.xml:13:9-58 value=(com.manu.module_two.TwoApplication).
Suggestion: add 'tools:replace="android:name"' to <application> element at AndroidManifest.xml:6:5-21:19 to override.
複製代碼
好比這裏就要在子 Module 中的 AndroidManifest 文件的 application 標籤下添加 tools:replace 屬性:ui
tools:replace="android:name"
複製代碼
除了 Application 須要合併以外,在組件化過程當中各個 Module 的初始化也很是重要,能夠使用發射完成各個 Module 的初始化,就是在主 Module 中反射獲取子 Module 的初始化對象,而後調用其初始化方法,爲了方便定義一個類管理子 Module 的初始化類,參考以下:
/**
* Created by jzman
* Powered by 2019/04/15 0022.
*/
public class ModuleConfig {
private static final String moduleOneInit = "com.manu.module_one.ModuleOneAppInit";
private static final String moduleTwoInit = "com.manu.module_two.ModuleTwoAppInit";
public static String[] moduleInits = {
moduleOneInit,
moduleTwoInit
};
}
複製代碼
建立一個初始化的基類接口以下:
/**
* 統一App初始化接口
* Created by jzman
* Powered by 2019/04/15 0022.
*/
public interface BaseAppInit {
/**
* 高優先級被初始化
* @param application
* @return
*/
boolean onInitHighPriority(Application application);
/**
* 低優先級被初始化
* @param application
* @return
*/
boolean onInitLowPriority(Application application);
}
複製代碼
爲了使得每一個子 Module 都能方便使用該初始化基類,應將其放在基類 Module 中,由於基類被全部的 Module 所依賴,而後在每一個字 Module 中繼承 BaseAppInit 實現本身 Module 的初始化類,參考以下:
/**
* module_one初始化文件
* Created by jzman
* Powered by 2019/04/15 0022.
*/
public class ModuleOneAppInit implements BaseAppInit {
private static final String TAG = ModuleOneAppInit.class.getSimpleName();
@Override
public boolean onInitHighPriority(Application application) {
Log.i(TAG, "ModuleOneAppInit---onInitHighPriority");
return true;
}
@Override
public boolean onInitLowPriority(Application application) {
Log.i(TAG, "ModuleOneAppInit---onInitLowPriority");
return true;
}
}
複製代碼
最後在主 Module 的自定義的 Application 中經過反射建立各個子 Module 的初始化類對象,並調用其初始化方法,參考以下:
/**
* 高優先級初始化
*/
private void initModuleHighPriority(){
for (String init: ModuleConfig.moduleInits){
try {
Class<?> clazz = Class.forName(init);
BaseAppInit appInit = (BaseAppInit) clazz.newInstance();
appInit.onInitHighPriority(this);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
}
}
/**
* 低優先級初始化
*/
private void initModuleLowPriority(){
for (String init: ModuleConfig.moduleInits){
try {
Class<?> clazz = Class.forName(init);
BaseAppInit appInit = (BaseAppInit) clazz.newInstance();
appInit.onInitLowPriority(this);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
}
}
複製代碼
運行日誌以下:
ModuleOneAppInit---onInitHighPriority
ModuleTwoAppInit---onInitHighPriority
ModuleOneAppInit---onInitLowPriority
ModuleTwoAppInit---onInitLowPriority
複製代碼
此外,還能夠在基類 Module 中建立初始化基類和 BaseApplication,而後在 BaseApplication 中反射調用調用具體的初始化方法,歸根結底仍是使用反射,只是另外一種實現方式,首先在基類 moddule 中建立 BaseAppInit 以下:
/**
* Created by jzman
* Powered by 2019/04/15 0022.
*/
public abstract class BaseAppInit {
private Application mApplication;
public BaseAppInit() {
}
public void setApplication(@NonNull Application application) {
this.mApplication = application;
}
public void onCreate(){}
public void OnTerminate(){}
public void onLowMemory(){}
public void configurationChanged(Configuration configuration){}
}
複製代碼
在基類 Module 中建立 BaseApplication 以下:
/**
* Created by jzman
* Powered by 2019/04/15 0023.
*/
public abstract class BaseApplication extends Application {
private List<Class<? extends BaseAppInit>> classInitList = new ArrayList<>();
private List<BaseAppInit> appInitList = new ArrayList<>();
@Override
public void onCreate() {
super.onCreate();
appInit();
initCreate();
}
protected abstract void appInit();
protected void registerApplicationInit(Class<? extends BaseAppInit> classInit) {
classInitList.add(classInit);
}
private void initCreate() {
for (Class<? extends BaseAppInit> classInit : classInitList) {
try {
BaseAppInit appInit = classInit.newInstance();
appInitList.add(appInit);
appInit.onCreate();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
@Override
public void onTerminate() {
super.onTerminate();
for (BaseAppInit appInit : appInitList) {
appInit.OnTerminate();
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
for (BaseAppInit appInit : appInitList) {
appInit.onLowMemory();
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
for (BaseAppInit appInit : appInitList) {
appInit.configurationChanged(newConfig);
}
}
}
複製代碼
而後在子 Module 中實現具體的初始化類,參考以下:
/**
* Created by jzman
* Powered by 2019/04/15 0023.
*/
public class ModuleThreeAppInit extends BaseAppInit {
private static final String TAG = ModuleThreeAppInit.class.getSimpleName();
@Override
public void onCreate() {
Log.i(TAG, "ModuleThreeAppInit---onCreate");
}
}
複製代碼
最後,在主 Module 中繼承 BaseApplication 實現自定義的 Application,並註冊每一個字 Module 的初始化文件,參考以下:
/**
* Created by jzman
* Powered by 2019/04/15 0023.
*/
public class MApplication extends BaseApplication{
@Override
protected void appInit() {
registerApplicationInit(ModuleThreeAppInit.class);
registerApplicationInit(ModuleForeAppInit.class);
}
}
複製代碼
運行日誌以下:
ModuleThreeAppInit---onCreate
ModuleForeAppInit---onCreate
複製代碼
如上兩種方式都是使用了反射,發射在解耦的同時,也在必定程度上下降了應用的性能,固然組件化的目的就是要讓各個組件或各個 Module 之間儘量的解耦,若是犧牲一點兒性能,可以獲取解耦的最大化也是能夠接受的。