美文网首页
关于安卓应用后台运行后,重新进入,应用闪退问题

关于安卓应用后台运行后,重新进入,应用闪退问题

作者: motosheep | 来源:发表于2020-06-06 05:52 被阅读0次

            现象:安卓应用后台运行后,在系统内存紧张下,应用会被kill掉,当用户点击应用图标重新进入的时候,就会闪退,大部分报错信息,都是空指针的错误。

            为什么会造成这种情况?首先,应用进程被kill掉(application被Kill,相关变量被清空),这个是可以确定的,但是,正常情况下(魔改过的rom不纳入考虑范围),应用的任务栈没有被清空,系统还是保留了原来应用的任务栈,当用户重新进入activity的时候,当用到某些已经被清空的变量时,就会NullPointerException报错。

            下面先说一下安卓activity的启动模式,分别为:Standard,SingleTop,SingleTask,SingleInstance。

            Standard:标准模式。默认的activity启动模式,也是我们最常用的模式。该模式下,activity启动会生成一个实例,然后进入我们调用的任务栈,假如原本的任务栈是:A-B-C,且当前显示的是C Activity,那么,C启动D,就会变成A-B-C-D,且D显示,D启动D,就会变成A-B-C-D-D,D显示,以上为Activity调用的情况。对于Application调用,需要加上new task标识,细心的读者,此时发现,生成的Activity是以singletask模式启动的。

            SingleTop:单一顶部模式,使用该模式的Activity,在启动的时候,会检查启动栈内的栈顶是否已经存在实例,若存在,则不会新建一个实例,会执行onNewIntent函数,注意onCreate(),onStart()方法不会执行。否则创建一个新的实例并入栈。例子:(1)当前任务栈为A-B-C,A为SingleTop模式,这个时候,C启动A,任务栈会变成A-B-C-A。(2)当前任务栈为A-B-C-A,A为SingleTop模式,这个时候,A启动A,任务栈还是A-B-C-A。

            SingleTask:栈内复用模式,使用该模式的Activity,在启动的时候,会检查启动栈内的栈顶是否已经存在实例,若存在,则不会新建一个实例,会清空其栈以上的Activity,使其成为栈顶Activity。并执行onNewIntent函数。若不存在,则新建一个任务栈,并且把Activity放入该任务栈中。

            SingleInstance:单实例模式,具有SingleTask的所有属性,并且启动该模式的Activity时,该Activity只能单独存在一个任务栈中。加入B启动了具有SingleInstance特性的A Activity,系统就会创建一个新的任务栈,并把A放入,后续启动A,都不会创建A的实例,除非A所在的任务栈被销毁。

            本次实战,MainActivity的启动模式为SingleTask,其余Activity的启动模式均为Standard。

            首先我们需要模拟应用进入后台,并且被系统Kill的情况。(这个有多种方法实现,作者使用的是手机开发者模式里面的不允许后台任务模式)

            情况1:应用打开了首页,退回后台,被系统kill后,重新进入应用,应用闪退,报空指针错。

            情况2:应用打开了二级页面,退回后台,被系统kill后,重新进入应用,应用闪退,同样报空指针错。

            思考:空指针报错,就是之前提及的系统Kill应用后,变量被释放造成的。那么我们如何处理?首先,被kill后的应用,用户再次点击进入,应用就会根据旧的任务栈信息进行复原Activity。由于Activity已经被销毁,所以Activity需要走重新创建的流程,重点就是,某些变量值,已经被释放了,这个时候,我选择的方法,就是在Activity的onCreate()方法里面,进行判断,如果是已经被销毁后,重新创建的Activity,这种情况下,我们直接启动MainActivity,然后在MainActivity的onNewInstance()方法里面判断,最后确定是否需要重新启动应用。

            再次提醒,上述使用情况,MainActivity的启动模式为SingleTask,其余Activity的启动模式均为Standard。其余的情况,其实也是大同小异,需要注意的是,各个Activity的启动模式,然后在对应的函数里面进行判断。

            返回代码,首先,我们定义一个类,用来记录Activity的启动:

    启动标识记录类 启动标识判断类

    当我们应用启动的时候,或者是在欢迎页面的时候,通过调用AppStatusManager,把mAppStatus的值设置为AppStatus类里面的正常态,如下图:

    设置正常态

    然后,在Activity的基类里面,onCreate方法中,加一个是否被后台Kill的判断(对于后台kill,变量值都会恢复到默认值),若是,则打开MainActivity,否则正常启动。(有人会问,为什么要打开MainActivity,而不是直接重启应用,这个是因为SingleTask的特别性,所以要特别处理)BaseActivity的onCreate处理逻辑如下图:

    BaseActivity onCreate方法处理

    走完上述的步骤,由于SingleTask的特别性,所以任务栈里面就剩一个MainActivity了。这个时候,我们要着手处理MainActivity的函数onNewIntent(),如下图:

    MainActivity onNewIntent

    这个情况进入,我建议是app进行finish掉MainActivity后,重启走一次启动流程的,这样更加符合规范。所以这里直接启动了欢迎页面,然后finish当前的MainActivity了。

    至此,问题修复完成,若有不正之处,请指出,定更正。

    相关文章

      网友评论

          本文标题:关于安卓应用后台运行后,重新进入,应用闪退问题

          本文链接:https://www.haomeiwen.com/subject/xlvozhtx.html