模組化-Application多module共存編譯生成解決方案

coolfire2015發表於2019-05-12

方案背景

元件化的一個目的是為了業務解耦,子 module 有些特殊功能的初始化需要在Application中完成,而殼 module 不需要知道具體如何完成這些初始化操作。這就需要解決多個 module 中Application共存的問題。

網上很多方案是使用反射或者在AndroidManifest中配置meta-data來實現。

這裡通過註解編譯時生成程式碼+反射實現,簡單方便,易於理解。

方案實現

  1. 初始化,子 module 和殼 module 中都需要如下配置。
dependencies {
    //框架核心包括註解和介面,可以單獨提取出來使用
    implementation 'com.github.coolfire2015.RxFluxArchitecture:core-arch:1.0.4'
    //註解編譯器
    annotationProcessor 'com.github.coolfire2015.RxFluxArchitecture:core-arch-processor:${RX_FLUX_ARCHITECTURE}'
}
複製程式碼
  1. 子 module 中建立AppLifecycle類實現RxAppLifecycle介面,並使用@RxAppDelegate標註。
@RxAppDelegate
public class GanAppLifecyle implements RxAppLifecycle {
    @Override
    public void onCreate(Application application) {
        EventBus.builder()
                .addIndex(new GanEventBusIndex())
                .eventInheritance(false);
    }
}
複製程式碼
  1. 殼 module 中的Application繼承RxApp類,並使用@RxAppBody標註。專案中唯一存在
@RxAppBody
public class SimpleApplication extends RxApp {
    
}
複製程式碼

方案原理

該方案採用GlideLibraryGlideModule的實現方式。

  1. 子 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 {
}
複製程式碼
  1. 殼 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);
        }
}
複製程式碼
  1. 如果有,則從當前包/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;
    }
複製程式碼
  1. 在殼 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);
  }
}
複製程式碼
  1. 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中,歡迎大家指正點贊。可以提取用到的程式碼,單獨編寫!

相關文章