当Android应用被强杀之后

   2016-09-11 0
核心提示:Android应用在后台运行的时候很容易被强杀,尤其是在国内XX助手、XX管家、XX大师之类的应用大行其道之下。如果我们开发的应用没有被用户加入白名单,很大程度上会被系统因为内存不足或者用户主动给应用在后台运行的时候杀掉。这个时候问题就来了:如何保证我

Android应用在后台运行的时候很容易被强杀,尤其是在国内XX助手、XX管家、XX大师之类的应用大行其道之下。如果我们开发的应用没有被用户加入白名单,很大程度上会被系统因为内存不足或者用户主动给应用在后台运行的时候杀掉。这个时候问题就来了:

  • 如何保证我们的应用在被强杀之后用户再次回到应用来保证应用的稳定性而不Crash?

为了说明上述问题,我们来简单模拟这样一个过程:

APP —> ActivityA —> ActivityB —>ActivityC —> Pressed Home

假设APP在Activity C页面用户按下 Home 键应用退到后台运行。这个时候启动DDMS,选中该APP的进程,Kill。然后我们从运行APP历史列表中选中该APP并将其置于前台,这个时候回到该应用的界面还是Activity C。再点击返回按钮回到ActivityB,在某些性能比较差一点的机器上可能会出现短暂的黑屏然后才会显示出ActivityB。这是因为该Activity实例其实在Kill该APP进程的时候已经被销毁了,但是Android系统虽然销毁了Activity实例,却并没有销毁该APP的Activity栈。因此我们点击返回按钮还是会回到ActivityB。但是需要重新构建该ActivityB的实例。

这样看貌似并没有什么问题,然而事情并不会这么简单(废话,不然我写这篇博客干嘛。。),如果ActivityB中引用了静态变量并尝试获取其值的时候,这个时候是会出现NPE的。

我们简单来总结下上述过程:

  1. 当应用在后台被Kill,整个APP进程都被销毁,所有变量都被清空,包括Application的实例。

  2. 虽然所有变量和实例都被销毁,但是Activity栈并没有被清空,所以我们回到应用还能得知页面的打开顺序。

  3. 当应用被强杀时,会自动调用 onSaveInstance 方法去保存一些核心变量,然而这在面对N多的页面的时候显然不是一件省心的事情,而且你也不能保证你的队友也会这么做。。

  4. 在某些性能比较低或者页面逻辑比较复杂的页面会黑屏是因为需要重建ActivityB的实例,也就是需要重走Activity的声明周期 OnCreate ,性能差点的机器上自然就会有短暂的黑屏了。

如果APP中没有静态变量的引用,那就不会出现NEP,但是一旦引用了静态变量,这个时候可能就比较危险了。(静态变量包括全局的登录状态,全局的用户配置、标志位之类的数据)当然了,如果你能将所有的静态变量修改到单例中去,并将其持久化,为NULL的时候再去取的话,原则上来说这样也可以避免NPE。然而要是这样做的话很大程度上会减缓开发的进度,而且指不定哪个队友就给你挖坑了。然后你怎么挂的都不知道。。

为了一劳永逸的解决这个问题,我们需要冷静下来思考一下: 既然APP被强杀了,为啥还要回到原先的页面中去而不是重走启动APP的流程?

我们虽然不能阻止Android系统销毁实例却保存Activity栈,也不想多写那些持久化或者Cache静态变量代码(这将是一件费力而且不太讨好的事情)所以我们唯一能做的就是检测应用是否被强杀,并且在被强杀之后重走启动流程而不是回到原先的逻辑当中。

以下给出我的一种实现方式,如果你有更好的想法,欢迎和我交流:


public abstract class BaseActivity extends AppCompatActivity {

private static int FLAG;
private final static int FLAG_NOT_INIT = 200;

@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (FLAG != FLAG_NOT_INIT) {
if (this.getClass() == LauncherActivity.class) {
FLAG = FLAG_NOT_INIT;
} else {
reLauncher();
}
}
}
}

我们实例化上述场景,给出一种对应关系:

ActivityA —> 启动页

ActivityB —> 主页

ActivityC —> 详情页

其中将ActivityB的 launchMode 设置为 singleTask ,并且在BaseActivity中使用静态变量FLAG进行判断当前应用是否被强杀,如果被强杀则利用ActivityB的 launchMode 特性清空栈并重新初始化即可。

有关Activity的启动模式相关文章,可参阅 Activity启动模式图文详解

 
标签: 安卓开发
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 安卓中通知功能的具体实现
    安卓中通知功能的具体实现
    通知[Notification]是Android中比较有特色的功能,当某个应用程序希望给用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知实现。使用通知的步骤1、需要一个NotificationManager来获得NotificationManager manager = (NotificationManager
    02-05 安卓开发
  • Android view系统分析-setContentView
    Android view系统分析-setContentView
    第一天上班,列了一下今年要学习的东西。主要就是深入学习Android相关的系统源代码,夯实基础。对于学习Android系统源代码,也没什么大概,就从我们平常使用最基础的东西学起,也就是从view这个切入点开始学习Android的源码,在没分析源码之前,我们有的时候
    02-05 安卓开发
  • 如何进行网络视频截图/获取视频的缩略图
    如何进行网络视频截图/获取视频的缩略图
    小编导读:获取视频的缩略图,截图正在播放的视频某一帧,是在音视频开发中,常遇到的问题。本文是主要用于点播中截图视频,同时还可以获取点播视频的缩略图进行显示,留下一个问题,如下图所示, 如果要获取直播中节目视频缩略图,该怎么做呢?(ps:直播是直
  • Android NDK 层发起 HTTP 请求的问题及解决
    Android NDK 层发起 HTTP 请求的问题及解决
    前言新的一年,大家新年快乐~~鸡年大吉!本次给大家带来何老师的最新文章~虽然何老师还在过节,但依然放心不下广大开发者,在此佳节还未结束之际,给大家带来最新的技术分享~ 事件的起因不说了,总之是需要实现一个 NDK 层的网络请求。为了多端适用,还是选择
  • Android插件化(六): OpenAtlasの改写aapt以防止资源ID冲突
    Android插件化(六): OpenAtlasの改写aapt以防
    引言Android应用程序的编译中,负责资源打包的是aapt,如果不对打包后的资源ID进行控制,就会导致插件中的资源ID冲突。所以,我们需要改写aapt的源码,以达到通过某种方式传递资源ID的Package ID,通过aapt打包时获取到这个Package ID并且应用才插件资源的命名
    02-05 安卓开发
  • Android架构(一)MVP架构在Android中的实践
    Android架构(一)MVP架构在Android中的实践
    为什么要重视程序的架构设计 对程序进行架构设计的原因,归根结底是为了 提高生产力 。通过设计是程序模块化,做到模块内部的 高聚合 和模块之间的 低耦合 (如依赖注入就是低耦合的集中体现)。 这样做的好处是使得程序开发过程中,开发人员主需要专注于一点,
    02-05 安卓开发
  • 安卓逆向系列教程 4.2 分析锁机软件
    安卓逆向系列教程 4.2 分析锁机软件
    安卓逆向系列教程 4.2 分析锁机软件 作者: 飞龙 这个教程中我们要分析一个锁机软件。像这种软件都比较简单,完全可以顺着入口看下去,但我这里还是用关键点来定位。首先这个软件的截图是这样,进入这个界面之后,除非退出模拟器,否则没办法回到桌面。上面那
    02-05 安卓开发
  • Android插件化(二):OpenAtlas插件安装过程分析
    Android插件化(二):OpenAtlas插件安装过程分析
    在前一篇博客 Android插件化(一):OpenAtlas架构以及实现原理概要 中,我们对应Android插件化存在的问题,实现原理,以及目前的实现方案进行了简单的叙述。从这篇开始,我们要深入到OpenAtlas的源码中进行插件安装过程的分析。 插件的安装分为3种:宿主启动时立
    02-05 安卓开发
  • [译] Android API 指南
    [译] Android API 指南
    众所周知,Android开发者有中文网站了,API 指南一眼看去最左侧的菜单都是中文,然而点进去内容还是很多是英文,并没有全部翻译,我这里整理了API 指南的目录,便于查看,如果之前还没有通读,现在可以好好看一遍。注意,如果标题带有英文,说明官方还没有翻
  • 使用FileProvider解决file:// URI引起的FileUriExposedException
    使用FileProvider解决file:// URI引起的FileUri
    问题以下是一段简单的代码,它调用系统的相机app来拍摄照片:void takePhoto(String cameraPhotoPath) {File cameraPhoto = new File(cameraPhotoPath);Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);takePhotoIntent.putExtra(Medi
    02-05 安卓开发
点击排行