方案背景
元件化的一個目的是為了業務解耦,子 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);
}
}
複製程式碼
原始碼
在開源模組化框架RxFluxArchitecture中,歡迎大家指正點贊。可以提取用到的程式碼,單獨編寫!