Android组件化之Application

原文首发于微信公众号:躬行之(jzman-blog)java

上一篇文章笼统的总结了一下组件化开发的一些基础性问题,本篇文章继续组件化的学习,主要分以下三个方面介绍组件化中的 Application 以下:android

  1. Application的做用
  2. 合并Application
  3. 动态配置Application

Application的做用

Androuid 应用的启动的时候最早启动的就是 Application,每一个 App 运行时仅建立惟一一个 Application,其生命周期就是 App 的生命周期,Application 中经常使用的回调方法以下:微信

  • onCreate:建立应用程序时回调,回调时机早于任何 Activity。
  • onTerminate:终止应用程序时调用,不能保证必定会被调用。
  • onLowmemory:当后台应用程序终止,但前台用用程序内存还不够时调用该方法,可在该方法中释放一些没必要要的资源来应对这种状况。
  • onConfigurationChanged:配置发生变化时回调该方法,如手机屏幕旋转等
  • onTrimMemory:通知应用的不一样内存状况,下面内存级别说明来自

其中附上一张来自Carson_Ho总结的 onTrimMemory 相关内存级别的说明以下:app

Application 做为整个 App 的一个单例对象,其做用以下:ide

  1. 做为 App 的入口,可用来初始化基本配置,如第三方 SDK 的初始化。
  2. 能够在 Application 中定义供全局使用的变量,不过当应用被强杀以后有可能出现空指针的问题,致使再次打开应用的时候崩溃,若是肯定要这样使用,必定要处理好这种状况。
  3. 能够借助 Application 管理 Activity 的生命周期状态以及判断应用处于前台仍是后台等,可根据内存优先级下降自身应用所占内存,减少自身应用被系统强杀的可能性。

合并Application

AndroidManifest 是每一个 Module 的声明配置文件,对应的在生成一个 App 的时候也应该对应一份 AndroidManifest 文件,那么在多个 Module 彼此依赖的状况下就须要合并子 Module 的 AndroidManifest 文件内容到主 Module 的 AndroidManifest 文件中,最终会在 build 目录下 生成最终的 AndroidManifest 文件,编译生成的 AndroidManifest 文件的具体路径参考以下:组件化

app\build\intermediates\manifests\full\debug\AndroidManifest.xml
复制代码

在合并子 Modulen 的 AndroidManifest 文件时,编译器会补全 use-sdk 的信息以及一些未设置的属性,在合并后如 Activity 等组件中的 name 属性都以包名+文件名来指定。post

其中在合并 AndroidManifest 文件要对 Application 进行合并, Application 合并规则以下:性能

  1. 若是子 Module 中有自定义的 Application,主 Module 中没有自定义 Application,则会将子 Module 中的 Application 合并到最终的 AndroidManifest 文件中。
  2. 若是主 Module 有自定义 Application,子 Module 没有自定义的 Application,则会在最终合并的 AndroidManifest 文件中使用主 Module 中的 Application。
  3. 若是多个子 Module 中都自定义了 Application,在解决冲突后则会在最终合并的 AndroidManifest 文件中使用最后编译的 Module 中的 Application。
  4. 若是子 Module 中有自定义的 Application,子 Module 中也有自定义的 Application,此时也会提示要在主 Module 的 AndroidManifest 文件中添加 tools:replace 属性,编译完成以后,合并后的 AndroidManifest 文件使用的是主 Module 中自定义的 Application。

在合并过程当中若是不添加 tools:replace 属性,则会提示添加 tools:android 属性,提示的错误信息以下:学习

Manifest merger failed : Attribute application@name value=(com.manu.module_one.OneApplication) from [:moduel_one] AndroidManifest.xml:13:9-58
    is also present at [:module_two] AndroidManifest.xml:13:9-58 value=(com.manu.module_two.TwoApplication).
    Suggestion: add 'tools:replace="android:name"' to <application> element at AndroidManifest.xml:6:5-21:19 to override.
复制代码

好比这里就要在子 Module 中的 AndroidManifest 文件的 application 标签下添加 tools:replace 属性:ui

tools:replace="android:name"
复制代码

动态配置Application

除了 Application 须要合并以外,在组件化过程当中各个 Module 的初始化也很是重要,能够使用发射完成各个 Module 的初始化,就是在主 Module 中反射获取子 Module 的初始化对象,而后调用其初始化方法,为了方便定义一个类管理子 Module 的初始化类,参考以下:

/**
 * Created by jzman
 * Powered by 2019/04/15 0022.
 */

public class ModuleConfig {
    private static final String moduleOneInit = "com.manu.module_one.ModuleOneAppInit";
    private static final String moduleTwoInit = "com.manu.module_two.ModuleTwoAppInit";
    public static String[] moduleInits = {
            moduleOneInit,
            moduleTwoInit
    };
}
复制代码

建立一个初始化的基类接口以下:

/**
 * 统一App初始化接口
 * Created by jzman
 * Powered by 2019/04/15 0022.
 */


public interface BaseAppInit {
    /**
     * 高优先级被初始化
     * @param application
     * @return
     */

    boolean onInitHighPriority(Application application);

    /**
     * 低优先级被初始化
     * @param application
     * @return
     */

    boolean onInitLowPriority(Application application);
}
复制代码

为了使得每一个子 Module 都能方便使用该初始化基类,应将其放在基类 Module 中,由于基类被全部的 Module 所依赖,而后在每一个字 Module 中继承 BaseAppInit 实现本身 Module 的初始化类,参考以下:

/**
 * module_one初始化文件
 * Created by jzman
 * Powered by 2019/04/15 0022.
 */


public class ModuleOneAppInit implements BaseAppInit {
    private static final String TAG = ModuleOneAppInit.class.getSimpleName();

    @Override
    public boolean onInitHighPriority(Application application) {
        Log.i(TAG, "ModuleOneAppInit---onInitHighPriority");
        return true;
    }

    @Override
    public boolean onInitLowPriority(Application application) {
        Log.i(TAG, "ModuleOneAppInit---onInitLowPriority");
        return true;
    }
}
复制代码

最后在主 Module 的自定义的 Application 中经过反射建立各个子 Module 的初始化类对象,并调用其初始化方法,参考以下:

/**
 * 高优先级初始化
 */

private void initModuleHighPriority(){
    for (String init: ModuleConfig.moduleInits){
        try {
            Class<?> clazz = Class.forName(init);
            BaseAppInit appInit = (BaseAppInit) clazz.newInstance();
            appInit.onInitHighPriority(this);
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 低优先级初始化
 */

private void initModuleLowPriority(){
    for (String init: ModuleConfig.moduleInits){
        try {
            Class<?> clazz = Class.forName(init);
            BaseAppInit appInit = (BaseAppInit) clazz.newInstance();
            appInit.onInitLowPriority(this);
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
    }
}
复制代码

运行日志以下:

ModuleOneAppInit---onInitHighPriority 
ModuleTwoAppInit---onInitHighPriority
ModuleOneAppInit---onInitLowPriority
ModuleTwoAppInit---onInitLowPriority
复制代码

此外,还能够在基类 Module 中建立初始化基类和 BaseApplication,而后在 BaseApplication 中反射调用调用具体的初始化方法,归根结底仍是使用反射,只是另外一种实现方式,首先在基类 moddule 中建立 BaseAppInit 以下:

/**
 * Created by jzman
 * Powered by 2019/04/15 0022.
 */

public abstract class BaseAppInit {

    private Application mApplication;

    public BaseAppInit() {
    }

    public void setApplication(@NonNull Application application) {
        this.mApplication = application;
    }

    public void onCreate(){}

    public void OnTerminate(){}

    public void onLowMemory(){}

    public void configurationChanged(Configuration configuration){}
}
复制代码

在基类 Module 中建立 BaseApplication 以下:

/**
 * Created by jzman
 * Powered by 2019/04/15 0023.
 */


public abstract class BaseApplication extends Application {

    private List<Class<? extends BaseAppInit>> classInitList = new ArrayList<>();
    private List<BaseAppInit> appInitList = new ArrayList<>();

    @Override
    public void onCreate() {
        super.onCreate();
        appInit();
        initCreate();
    }

    protected abstract void appInit();

    protected void registerApplicationInit(Class<? extends BaseAppInit> classInit) {
        classInitList.add(classInit);
    }

    private void initCreate() {
        for (Class<? extends BaseAppInit> classInit : classInitList) {
            try {
                BaseAppInit appInit = classInit.newInstance();
                appInitList.add(appInit);
                appInit.onCreate();

            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        for (BaseAppInit appInit : appInitList) {
            appInit.OnTerminate();
        }
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        for (BaseAppInit appInit : appInitList) {
            appInit.onLowMemory();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        for (BaseAppInit appInit : appInitList) {
            appInit.configurationChanged(newConfig);
        }
    }
}
复制代码

而后在子 Module 中实现具体的初始化类,参考以下:

/**
 * Created by jzman
 * Powered by 2019/04/15 0023.
 */


public class ModuleThreeAppInit extends BaseAppInit {
    private static final String TAG = ModuleThreeAppInit.class.getSimpleName();

    @Override
    public void onCreate() {
        Log.i(TAG, "ModuleThreeAppInit---onCreate");
    }
}
复制代码

最后,在主 Module 中继承 BaseApplication 实现自定义的 Application,并注册每一个字 Module 的初始化文件,参考以下:

/**
 * Created by jzman
 * Powered by 2019/04/15 0023.
 */


public class MApplication extends BaseApplication{
    @Override
    protected void appInit() {
        registerApplicationInit(ModuleThreeAppInit.class);
        registerApplicationInit(ModuleForeAppInit.class);
    }
}
复制代码

运行日志以下:

ModuleThreeAppInit---onCreate
ModuleForeAppInit---onCreate
复制代码

如上两种方式都是使用了反射,发射在解耦的同时,也在必定程度上下降了应用的性能,固然组件化的目的就是要让各个组件或各个 Module 之间尽量的解耦,若是牺牲一点儿性能,可以获取解耦的最大化也是能够接受的。

相关文章
相关标签/搜索