android 组件化开发—多个Module的Application初始化共存问题

一个重点:

在Application里,attachBaseContext()方法的执行顺序是在onCreate()之前的

组件化的目的是为了业务解耦,每个业务模块需要不同的功能,例如车辆详情模块需要第三方分享,城市定位模块需要百度地位等。有些特殊功能的初始化需要在 Application 中去做,但是这些功能并非全部业务组件都用到的东西,放到 主工程Application 不合适。
因此,我想这样操作:

模块共有的初始化,放入主工程Application 中。
模块自身的特殊功能初始化,放在自己的 Application。
想法很美好,但实现前需要先思考一个问题:

多 Module 项目开发的时候,app module 和 library module 的 都有不同的自定义 Application ,可以共存并且自动合并吗?

答案是 No。

为啥不行?

首先,自定义 Application 需要声明在 AndroidManifest.xml 中。其次,每个 Module 都有该清单文件,但是最终的 APK 文件只能包含一个。因此,在构建应用时,Gradle 构建会将所有清单文件合并到一个封装到 APK 的清单文件中。

合并的优先级是:

App Module > Library Module在这里插入图片描述
如果值 A 合并值 B,就会产生冲突错误,错误信息中给出了解决建议,在高优先级的 App Module 中使用 tools:replace=“android:name”,但这样做是直接用值 A 替换了值 B,并非我们想要的结果。

所以我们知道:

APP打开的时候,只会初始化主工程的application(打开主工程AndroidManifest,点击Merged
Manifest,就可以看到,其他的Module的application都被覆盖了,只剩下主工程application)

所以,换个道路走,在初始化主工程application的时候,对其他module的application进行初始化。

了解一下我们平时用到的getApplicationContext()和getBaseContext():
Application本身是没有getApplicationContext()和getBaseContext()这两个方法的,这两个方法其实在Application的父类ContextWrapper中,其中context是在attachBaseContext(Context base)中赋值的,所以我们重写attachBaseContext的时候,一定要记得调一遍super.attachBaseContext(base)传入当前context。

了解清楚Application的生命周期,那我们初始化module的application就操作就可以做了

主工程的application:

<table class="hljs-ln"><tbody><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="1"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="1">public class MainApplication extends Application {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="2"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="2"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="3"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="3">    private ModuleApplication moduleApplication;//module的Application映射</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="4"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="4"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="5"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="5"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="6"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="6">    @Override</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="7"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="7">    public void onCreate() {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="8"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="8">        super.onCreate();</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="9"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="9"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="10"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="10">        //....一些主工程的初始化操作</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="11"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="11"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="12"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="12">        //同步Module的Application的onCreate</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="13"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="13">        if (moduleApplication != null){</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="14"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="14">            moduleApplication.onCreate();//用于执行module的一些自定义初始化操作</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="15"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="15">        }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="16"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="16">    }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="17"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="17"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="18"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="18">    @Override</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="19"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="19">    protected void attachBaseContext(Context base) {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="20"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="20">        super.attachBaseContext(base);</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="21"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="21"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="22"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="22">        moduleApplication = getModuleApplicationInstance(this);</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="23"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="23">        try {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="24"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="24">            //通过反射调用moduleApplication的attach方法</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="25"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="25">            Method method = Application.class.getDeclaredMethod("attach", Context.class);</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="26"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="26">            if (method != null) {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="27"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="27">                method.setAccessible(true);</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="28"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="28">                method.invoke(moduleApplication, getBaseContext());</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="29"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="29">            }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="30"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="30">        } catch (Exception e) {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="31"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="31">            e.printStackTrace();</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="32"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="32">        }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="33"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="33">    }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="34"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="34"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="35"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="35">    //映射获取ModuleApplication</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="36"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="36">    private ModuleApplication getModuleApplicationInstance(Context paramContext) {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="37"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="37">        try {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="38"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="38">            if (moduleApplication == null) {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="39"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="39">                ClassLoader classLoader = paramContext.getClassLoader();</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="40"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="40">                if (classLoader != null) {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="41"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="41">                    Class&lt;?&gt; mClass = classLoader.loadClass(ModuleApplication.class.getName());</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="42"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="42">                    if (mClass != null)</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="43"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="43">                        moduleApplication = (ModuleApplication) mClass.newInstance();</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="44"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="44">                }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="45"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="45">            }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="46"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="46">        } catch (Exception e) {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="47"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="47">            e.printStackTrace();</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="48"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="48">        }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="49"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="49">        return moduleApplication;</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="50"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="50">    }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="51"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="51">}</td></tr></tbody></table>

可以看到,实际上就是主工程的Application和module的Application共用一个base,最后我们想要的结果也实现了。

Module的application (不用在Module的AndroidManifest中注册)

<table class="hljs-ln"><tbody><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="1"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="1">public ModuleApplication extends Application{</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="2"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="2">    private static ModuleApplication instance;</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="3"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="3">    </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="4"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="4">    public void onCreate(){</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="5"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="5">        super.onCreate();</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="6"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="6">        //...一些自定义操作</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="7"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="7">        instance = this;</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="8"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="8">    }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="9"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="9"> </td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="10"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="10">    public static getInstance(){</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="11"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="11">        return instance;</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="12"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="12">    }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="13"></td><td class="hljs-ln-line hljs-ln-code" data-line-number="13">}</td></tr></tbody></table>

这样,主工程和Module的Application都能启动并初始化了,并且根据打印的log,查看各自的运行进程【Process.myPid()】,可以看到他们运行在同一个进程里,即应用默认的唯一主进程

posted @ 2023-03-21 10:56  cps666  阅读(299)  评论(0编辑  收藏  举报