简单的 applicappation 通用组件

开场白

今天突然有感,想写一个通用的 application 组件出来,应该是对 application 的思考和积累有点心得了,要不怎么会突然冒出这个想法呢

在项目中我们都会一个 MainApplication 类承载我们 application 中的逻辑,期中有很大一部分逻辑代码都是通用的,考虑到平台化的问题(我司内部就有好几个 app),怎么复用 application 是个问题。还有一部分功能和业务组件时需要 applicationContent 的,所以怎么跨 app 通用 application 是个问题。

application 组件思路

application 抽象成公共组件是个必然,但是在 app 内我们不能简单的复用 application 类型,每个 app 中的application 都是不同的,所以难点在于怎么让 application 可以实现跨 app 。

上面的问题可以使用代理的思路,全局静态的 applicationProxy 对象持有 app 的 application 对象,这样统一了 application 类型,我们就能在任何地方使用 application 了。

另外添加了一些 application 常用的功能:

  • app 启动,home 键切入后台,切回前台的回调和状态记录
  • 手机信息采集
  • 栈管理(类我声明了,具体逻辑没写)
  • app 进程回收优化

application 组件分层

因为要实现的功能不多,我也不打算写多少,所以 application 组件功能分层很简单,有下面几个类:

  • ApplicationComponent
    application 组件外部公共入口
  • AppStateManage
    app 状态记录器,有4个标记位:app 启动,进入后台,进入前台,当前状态
  • ActivityManage
    app activity 栈管理
  • PhoneInfoManage
    手机信息采集器
  • ListenerAdapter
    回调适配器
AppStateManage

AppStateManage 定义的4个 app 状态值需要搞清楚

    // app 首次启动
    public static final int STATE_APPSTATE = 0;
    // app 在前台
    public static final int STATE_FRONT = 1;
    // app 在后台
    public static final int STATE_BACKGROUD = -1;
    // app 当前状态
    public int currentState = STATE_APPSTATE;
ApplicationComponent
public class ApplicationComponent {

    ..............

    public void attach(Application application) {

        if (application != null) {
            this.application = application;
            initParameter();
            registerActivityLifecycleCallback();
        }
    }
 }

ApplicationComponent 因为要对外提供统一的公共入口,所以静态单例是没跑了

ApplicationComponent 核心就是 attach 方法,attach 方法会关联 app 的 application 对象并给 application 对象注册 ActivityLifecycleCallbacks 全局回调监听函数,Application 组件的核心功能都是在这里实现的

ActivityManage

ActivityManage 应该是实现 activity 栈管理的,我这里没做。我在 ActivityManage 里面记录了活动窗口数量,这个参数是判断 app 在后台还是前台的核心。

app 启动,前台,后台的判断思路

这个需求大家应该都碰到过,但是 android API 对这个需求真是无能为力,需要自己想办法,我在上一个项目的日志模块碰到的这个需求,需要准确区分 app 的启动,切入后台,切回前台。

我的思路很简单,就是利用 application 注册的 ActivityLifecycleCallbacks 全局监听函数中的 activityStart 和 activityStop 方法中记录当前活跃的窗口数。

  • AppStateManage 中的 currentState 默认是 app 启动
  • activityStart 函数:
    * 先判断 currentState 是不是 app 启动标记,是的话,执行 app 启动的回调函数,然后currentState 置为前台标记,然后活动窗口数++,return
    * 若 currentState 不是 app 启动标记,并且活动窗口数为0的话,表示切回前台,然后活动窗口数++,return
  • activityStop 函数,活动窗口数先 — ,若活动窗口数为0的话,app 就进入后台了。

用这个思路,判断 app 是不是首次启动,home 切入后台,切回前台很准确,并且把这端逻辑放在 applicappation 组件中,适合别的组件调用,尤其是在推送中判断当前 app 的状态是个很好的做法。

另外我在 ActivityManage 中只记录了活动窗口数,大家可以自行扩展线管公共,比如有的组件需要获取到当前活动的 activity 对象的,放到 ActivityManage 挺合适的。

APP 进程优化

这个是应对一个问题: 系统杀后台的 app 进程会缓存 activity 栈信息,再次由系统启动 app 进程的话,界面会直接来到上次的位置。

这就带来一个问题,我们在 flashActivity 中会写很多启动逻辑和初始化操作,要是有 activity 栈缓存的话,就不会执行正常的启动逻辑了,flashActivity 页面就没法执行了,有次会带来很多问题,尤其是初始化方法没有执行造成的空指针。我们在写日志模块时,因为需要读写 SD 卡的权限,所以日志组件的初始化放到 flashActivity 里,结果就因为这个 activity 栈缓存的问题报了很多次空指针,教训啊!

那么面对这个问题怎么解决呢,就是在 app 处于后台进程,并且快被回收时,不用等系统回收,咱们自己杀自己,这样就没有 activity 栈缓存的问题了,app 启动逻辑永远都会按我们设计的走,对我们就没有干扰了。

关于后台进程回收优先级的点看我这篇文章:

关于杀进程的问题再补充一下,app 处于后台时不管我们怎么杀进程都没事,但是 app 在前台时我们杀进程,进程的确会被杀死,但是进程在被杀死之后还会重启,没有 activity 栈缓存的问题,会按正常逻辑启动 app

杀进程的方法如下:

最后

项目地址: BW_Application

完事之后,感觉写的很一般,太菜了,功能是分层了,但是逻辑没有完全分层,尤其是对 app 启动,后太,前台的逻辑判断上,全都放在作为外部入口的 ApplicationComponent 类里了,这对不熟悉这个组件的朋友和未来的自己修改维护带来了麻烦和困扰,一是逻辑位置不好找,二是不方便扩展。引以为戒吧,从小处看代码封装的水平,代码封装的水平基本就代表了手底下的代码编写水平,我这也是不合格呀。

大家就胡看吧,小白太菜没办法……

参考资料

    原文作者:前行的乌龟
    原文地址: https://www.jianshu.com/p/87ed1d0b7a2f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞