开始之前,顺带提一下一个小知识,那就是:

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

下面开始说明Android中,多个module是怎么初始化application,让module的application拥有实例的。

方法说起来很简单,就是使用反射。

因为软件打开的时候,只会初始化主工程的application(打开主工程AndroidManifest,点击Merged Manifest,就可以看到,其他的application都被覆盖了,只剩下主工程application),所以在这里,我就想到在初始化主工程application的时候,对其他module的application进行初始化。

最开始我是这样做的
在主工程的application里的onCreate方法里
 

//主工程Applicationpublic class MainApplication extends Application{    public void onCreate(){        super.onCreate();        //.....中间执行主工程的一些初始化操作                //初始化module的application        try{            Class<?> clazz = Class.forName(ModuleApplication.class.getName());            ModuleApplication moduleApplication = (ModuleApplication)clazz.newInstance();            moduleApplication.onCreate();        }catch(Exception e){            Log.e("ALeeObj", e.getMessage);        }    }}

试了一下,发现完全没有用,该报null Object还是报了。

我想知道,我们平时用到的getApplicationContext()和getBaseContext()到底怎么实现的?

于是我去看看Application的源码,有点意外的发现,Application本身是没有getApplicationContext()和getBaseContext()这两个方法的。但同时我也看到Application还继承了一个叫ContextWrapper的类
 

于是我跑去ContextWrapper的类看看,果然发现了这两个方法

看来问题就在这个mBase里了,可以看到源码的注释,这个mBase是在构造方法里或者setBaseContext里设置的,然而,我找了整个类,也没找到setBaseContext这个方法,只能去构造方法看看。

看上去是在构造方法里设置值了,直到我跑回我们的主角Application里看看

坑啊,派生类Application里直接把null传进了ContextWrapper的构造方法。那ContextWrapper的mBase到底是在哪里赋值的呢?

实际上,mBase的赋值还是在ContextWrapper里赋值的

是不是感觉很熟悉,就是在这个我们常用的attachBaseContext里赋值的,所以我们重写attachBaseContext的时候,一定要记得调一遍super.attachBaseContext()啊。那attachBaseContext是在什么时候调用的呢?找了一下,发现原来还是在Application里调用的,这也解释了为什么我们使用主工程的application的时候不会报null Object的错误。

而attach是在什么时候调用的,我暂时还没找到,希望哪位大佬可以分享一下。

既然知道了application最需要初始化的mBase在哪里初始化,那我们初始化module的application就操作就变得很清晰了。下面直接上代码。

public class MainApplication extends Application {    private ModuleApplication moduleApplication;//module的Application映射    @Override    public void onCreate() {        super.onCreate();        //....一些主工程的初始化操作        //同步Module的Application的onCreate        if (moduleApplication != null){            moduleApplication.onCreate();//用于执行module的一些自定义初始化操作        }    }    @Override    protected void attachBaseContext(Context base) {        super.attachBaseContext(base);        moduleApplication = getModuleApplicationInstance(this);        try {            //通过反射调用moduleApplication的attach方法            Method method = Application.class.getDeclaredMethod("attach", Context.class);            if (method != null) {                method.setAccessible(true);                method.invoke(moduleApplication, getBaseContext());            }        } catch (Exception e) {            e.printStackTrace();        }    }    //映射获取ModuleApplication    private ModuleApplication getModuleApplicationInstance(Context paramContext) {        try {            if (moduleApplication == null) {                ClassLoader classLoader = paramContext.getClassLoader();                if (classLoader != null) {                    Class<?> mClass = classLoader.loadClass(ModuleApplication.class.getName());                    if (mClass != null)                        moduleApplication = (ModuleApplication) mClass.newInstance();                }            }        } catch (Exception e) {            e.printStackTrace();        }        return moduleApplication;    }}

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

在这里额外说明一下,我们初始化了ModuleApplication肯定是想用的,但使用时要注意一下,如果直接在module里使用getApplication(),获取到的仍然是主工程的Application,因而,如果想使用ModuleApplication,一个比较好的方式是保存下来application对象。例如:

public ModuleApplication extends Application{    private static ModuleApplication instance;        public void onCreate(){        super.onCreate();        //...一些自定义操作        instance = this;    }    public static getInstance(){        return instance;    }}

很简单,就是初始化后把对象保存下来,之后要用到Module Application时,就用ModuleApplication.getInstance()。

更多相关文章

  1. ANDROID开机动画bootanimation.zip的详细制作方法
  2. [译]提升Android应用性能的小贴士
  3. Android(安卓)图解向 Android(安卓)Studio 中导入 Eclipse 工程
  4. [置顶] android软键盘弹出,会把原来的界面挤上去的问题 处理方法
  5. Android(安卓)面试精华题目总结
  6. Android设置背景色为透明的两种方法
  7. Android(安卓)应用初始化及窗体事件的分发
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. 文件系统中的保留空间
  2. android去掉头部label的方法
  3. android —— 常用代码utils
  4. ANDROID STUDIO 自动更新失败之解决办法
  5. android判断网络连接状态-ConnectivityMa
  6. android开发中遇到的问题汇总【九】
  7. 图片上动态添加文字
  8. Android TabHost每个Tab的Activity事件
  9. 《Android(安卓)Dev Guide》系列教程9:用
  10. Android实现圆形图片的两种方式