模組化-Application多module共存編譯生成解決方案
元件化的一個目的是為了業務解耦,子 module 有些特殊功能的初始化需要在Application
中完成,而殼 module 不需要知道具體如何完成這些初始化操作。這就需要解決多個 module 中Application
共存的問題。
網上很多方案是使用反射或者在AndroidManifest
中配置meta-data
來實現。
這裡通過註解編譯時生成程式碼+反射實現,簡單方便,易於理解。
方案實現
- 初始化,子 module 和殼 module 中都需要如下配置。
dependencies { //框架核心包括註解和介面,可以單獨提取出來使用 implementation 'com.github.coolfire2015.RxFluxArchitecture:core-arch:1.0.4' //註解編譯器 annotationProcessor 'com.github.coolfire2015.RxFluxArchitecture:core-arch-processor:${RX_FLUX_ARCHITECTURE}' } 複製程式碼
-
子 module 中建立
AppLifecycle
類實現RxAppLifecycle
介面,並使用@RxAppDelegate
標註。
@RxAppDelegate public class GanAppLifecyle implements RxAppLifecycle { @Override public void onCreate(Application application) { EventBus.builder() .addIndex(new GanEventBusIndex()) .eventInheritance(false); } } 複製程式碼
-
殼 module 中的
Application
繼承RxApp
類,並使用@RxAppBody
標註。專案中唯一存在
@RxAppBody public class SimpleApplication extends RxApp { } 複製程式碼
方案原理
該方案採用Glide
中LibraryGlideModule
的實現方式。
-
子 module 中,
@RxAppDelegate
標註的RxAppLifecycle
介面實現類,編譯後會在子 module 路徑/build/generated/source/apt/debug/com/huyingbao/core/processor/
下會生成一個索引類RxIndexer_包名_類名.java
。
@RxIndex( modules = "com.huyingbao.module.wan.action.WanAppLifecyle" ) public class RxIndexer_com_huyingbao_module_wan_action_WanAppLifecyle { } 複製程式碼
-
殼 module 在編譯過程中,編譯處理器
RxArchProcessor
檢查程式碼中是否唯一有使用@RxAppBody
標註並繼承RxApp
的類
private void processRxAppBody(RoundEnvironment env) { for (TypeElement element : mProcessorUtil.getElementsFor(RxAppBody.class, env)) { if (mProcessorUtil.isRxApp(element)) { mRxAppList.add(element); } } mProcessorUtil.debugLog("got app modules: " + mRxAppList); if (mRxAppList.size() > 1) { throw new IllegalStateException("You cannot have more than one RxApp, found: " + mRxAppList); } } 複製程式碼
-
如果有,則從當前包
/com/huyingbao/core/processor/
附加的類中獲取到所有子 module 中編譯生成的RxIndexer_
類,再從RxIndexer_
類的註解@RxIndex
中取出 modules 欄位中儲存的RxAppLifecycle
介面實現類名。
private Set<String> getIndexedClassNames(PackageElement packageElement) { Set<String> rxAppLifecycles = new HashSet<>(); //獲取當前包元素附加的所有元素 List<? extends Element> rxAppLifecycleGeneratedElements = packageElement.getEnclosedElements(); for (Element indexer : rxAppLifecycleGeneratedElements) { RxIndex annotation = indexer.getAnnotation(RxIndex.class); // If the annotation is null, it means we've come across another class in the same package // that we can safely ignore. if (annotation != null) { Collections.addAll(rxAppLifecycles, annotation.modules()); } } mProcessorUtil.debugLog("Found RxAppLifecycle: " + rxAppLifecycles); return rxAppLifecycles; } 複製程式碼
-
在殼 module 路徑
/build/generated/source/apt/debug/com/huyingbao/core/arch/
下會生成一個RxAppLifecycle
實現類RxAppLifecycleImpl
。
final class RxAppLifecycleImpl implements RxAppLifecycle { @Override public void onCreate(Application application) { new GanAppLifecycle().onCreate(application); new WanAppLifecyle().onCreate(application); } } 複製程式碼
-
在
RxApp
類中通過反射獲取RxAppLifecycleImpl
例項物件。
private RxAppLifecycle getAnnotationGeneratedRxAppLifecycleImpl() { RxAppLifecycle result = null; try { Class<RxAppLifecycle> clazz = (Class<RxAppLifecycle>) Class.forName("com.huyingbao.core.arch.RxAppLifecycleImpl"); result = clazz.getDeclaredConstructor().newInstance(); } catch (ClassNotFoundException e) { if (Log.isLoggable(TAG, Log.WARN)) { Log.w(TAG, "Failed to find RxAppLifecycleImpl. You should include an" + " annotationProcessor compile dependency on com.github.coolfire2015.RxFluxArchitecture:core-arch-processor" + " in your application and a @RxAppDelegate annotated RxAppLifecycle implementation" + " and a @RxAppBody annotated RxApp implementation"); } // These exceptions can't be squashed across all versions of Android. } catch (InstantiationException e) { throwIncorrectRxAppLifecycle(e); } catch (IllegalAccessException e) { throwIncorrectRxAppLifecycle(e); } catch (NoSuchMethodException e) { throwIncorrectRxAppLifecycle(e); } catch (InvocationTargetException e) { throwIncorrectRxAppLifecycle(e); } return result; } 複製程式碼
在Application
生命週期方法中呼叫RxAppLifecycleImpl
例項物件中的對應方法。
private RxAppLifecycle mGlobalRxAppLifecycle; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); mGlobalRxAppLifecycle = getAnnotationGeneratedRxAppLifecycleImpl(); } @Override public void onCreate() { super.onCreate(); if (mGlobalRxAppLifecycle != null) { mGlobalRxAppLifecycle.onCreate(this); } } 複製程式碼