Android保活机制

一 背景

正常的页面关闭的时候是会把当前的页面全部销毁,然后二次打开的时候在重新创建。但是很多场景下,二次打开其实并不需要打开新的页面,或者就算打开新的页面,由于小程序有后台的work统一管理多个页面,所有也不需要重新在Native层面重启app。所以小程序做了保活,在退出的时候不会把页面销毁,达到了二次秒开的效果。

二 实现原理

2.1 拦截正常的返回

 我们都知道正常的Activity返回键会直接把activity给finish掉,首先要做的就是在返回的时候不把activity销毁掉。Android里的activity都是运行在各自的task内,所以只需要操作task栈即可。要做的事情分为两步:1. 小程序打开的页面和之前打开的页面不在一个task内;2. 拦截小程序页面的返回,把上一个task搬到前台,在把当前小程序页面所在的task搬到后台。

 要保证小程序页面在新的task内,单独设置intent.setFlags\(Intent.FLAG\_ACTIVITY\_NEW\_TASK\)是没用的,还要在小程序的activity的配置里添加taskAffinity属性。因为如果没有配置taskAffinity属性,还是默认会把activity 添加在当前已经存在的task内。

然后是拦截页面的返回事件,首先把小程序上一个页面的task堆栈:moveTaskToFront,然后在把当前的堆栈moveTaskToBack。这样就实现了返回的时候并没有实际销毁页面的目的。

2.2 重启保活实例获取最新参数

 二次重启的时候,有一个重要的功能,就是需要把二次重启的新参数获取出来。可以通过Activity的onNewIntent获取到。有两种实现方案:
  1. 把activity声明为singleTask,这样二次重启的时候,系统会自动回到onNewIntent,获取到当前的最新参数。
  2. activity还是用默认的配置,保活唤起的时候intent设置FLAG_ACTIVITY_SINGLE_TOP。这样也能回调onNewIntent。

    对比而言,方案1对代码侵入更低,只需要更改配置文件即可。

三 遇到的问题

3.1 内存问题

 后台保活首先考虑到的就是内存问题,所以小程序不会在后台一直存留,会有一定的保活时间,超期自动销毁。还有就是类似音乐播放等多媒体播放类的页面,需要监听压后台的事件,不然在保活后会有一直播放的问题。

3.2 认知问题

 由于和正常的页面退出不同,所以对业务开发其实也需要教育成本,让业务理解保活的概念以及使用方式。

3.3 页面后退栈乱的问题

  A-B\(小程序\)-C,由于B设置了自己单独的taskAffinity属性,如果启动C的intent有FLAG\_ACTIVITY\_NEW\_TASK,系统会把C的task堆栈加到A的后面,会出现返回C的时候直接返回到A的页面,跳过了B,导致返回路径不完整。解决方案:拦截从容器startActivity的场景,对会造成返回堆栈乱的场景进行纠正。

四 业务使用

 保活唤起的时候,容器会给AppX发出appResume事件,事件里携带二次重启的参数。appx在收到数据后,会把新的参数回调到app的onShow事件。业务层就可以获取到当前最新的数据,自己做业务逻辑。如果二次打开的参数携带了新打开的page参数,AppX会主动调用一次reLaunch接口,关闭其他窗口后打开指定的page窗口。由于Native已经创建好,所以不管哪种场景,速度都可以得到保障,达到二次秒开的效果。

results matching ""

    No results matching ""