Android应用运行在后台的时候,经常被系统的LowMemoryKiller杀掉,当用户再次点击icon或者从最近的任务列表启动的时候,进程会被重建,并且恢复被杀之前的现场。什么意思呢?假如APP在被杀之前的Activity堆栈是这样的,A<B<C,C位于最上层

APP被后台杀死后,APP端进程被销毁了,也就不存在什么Activity了,也就没有什么Activity堆栈,不过AMS的却是被保留了下来:

当用户再次启动APP时候会怎么样呢?这个时候,首先看到其实C,而不是栈底部的A,也就是说往往被杀死后,恢复看到的第一个界面是用户最后见到的那个界面。

而用户点击返回,看到的就是上一个界面B,其次是A

之所以这样是因为APP端Activity的创建其实都是由AMS管理的,AMS严格维护这APP端Activity对应的ActivityRecord栈,可以看做当前APP的场景,不过,APP端Activity的销毁同AMS端ActivityRecord的销毁并不一定是同步的,最明显的就是后台杀死这种场景。Android为了能够让用户无感知后台杀死,就做了这种恢复逻辑,不过,在开发中,这种逻辑带了的问题确实多种多样,甚至有些产品就不希望走恢复流程,本文就说说如何避免走恢复流程。结合常见的开发场景,这里分为两种,一种是针对推送唤起APP,一种是针对从最近任务列表唤起APP(或者icon)。

从最近的任务列表唤起,不走恢复流程

首先,APP端必须知道当前Activity的启动是不是在走恢复流程,Activity有一个onCreate方法,在ActivityThread新建Activity之后,会回调该函数,如果是从后台杀死恢复来的,回调onCreate的时候会传递一个非空的Bundle savedInstanceState给当前Activity,只要判断这个非空就能知道是否是恢复流程。

@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}
复制代码

知道恢复流程之后,如何处理呢?其实很简单,直接吊起闪屏页就可以了,不过这里有一点要注意的是,在启动闪屏页面的时候,必须要设置其IntentFlag:Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK,这样做的理由是为了清理之前的场景,不然之前的ActivityRecord栈仍然保留在ActivityManagerService中,具体实现如下,放在BaseActivity中就可以:

Intent intent = new Intent(this, SplashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
复制代码

如果不设置会怎么样呢?举个例子,最常见的就是闪屏之后跳转主界面,主界面经常有router逻辑,并且其启动模式一般都是singleTask,处理一些推送,所以其onCreate跟onNewIntent都有相应的处理,如果不设置,在闪屏结束后,在startActivity启动主界面的时候,其实是先走恢复逻辑,然后走singleTask的onNewIntent逻辑,也就是说,onNewIntent跟onCreate是会同时调用的,也可能就会引发重复处理的逻辑,因此最好清理干净。

从推送唤起被杀APP时,如何走闪屏逻辑

对于推送消息的处理,其路由器一般放在MainActivity,并且在onCreate跟onNewIntent都有添加,如果APP存活的情况,可以直接跳转目标页面,如果APP被杀,这个时候,希望先跳转主界面,再跳转目标页面,在效果上来看就是,用户先看到目标页面,点击返回的时候再看到主界面,如果加上闪屏,希望达到的效果是先看到闪屏、点击返回看到目标页,再点击返回看到主页面。如果简单划分一下推送场景,可以看做一下三种

  • 进程存活,Activity存活
  • 进程存活,但是没有Activity存活
  • 进程不存在(无论是否被杀)

其实后面两种完全可以看做一种,这个时候,都是要先start MainActivity,然后让MainActivity在其OnCreate中通过startActivityForResult启动SplashActivity,SplashActivity返回后,在start TargetActivity。下面的讨论都是针对后面两种,需要做的有两件事

  • 一是:检测出后面两种场景,并且在唤起主界面的时候需要添加Intent.FLAG_ACTIVITY_CLEAR_TASK清理之前的现场
  • 二是:在MainActivity的路由系统中,针对这两种场景要,先跳转闪屏,闪屏回来后,再跳转推送页

如何判断呢,后面两种场景其实只需要判断是否有Activity存活即可,也就是查查APP的topActivity是否为null,注意不要去向AMS查询,而是在本地进程中查询,可以通过反射查询ActivityThread的mActivities,也可以根据自己维护的Activity堆栈来判断,判断没有存活Activity的前提下,就跳转主页面去路由

Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setDate(跳转的Uri scheme)
startActivity(intent);
复制代码

在MainActivity的路由中,需要准确区分是否是推送跳转进来的,如果不是推送跳转进来,就不需要什么特殊处理,如果是推送跳转进来一定会携带跳转scheme数据,根据是否携带数据做区分即可,看一下MainActivity的代码:

@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Uri uri= getIntent().getData();<!--只有在intent被设置了跳转数据的时候才去跳转,一般是推送就来,如果冷启动,是没有数据的-->if(uri!=null){SplashActivity.startActivityForResult(this,JUMP_TO_TARGET)}
}
<!--Intent.FLAG_ACTIVITY_CLEAR_TASK保证了onNewIntent被调用的时候,进程一定是正常活着的-->
@Override
protected void onNewIntent(Intent intent) {Uri uri= intent.getData();intent.setData(null);router(uri);
}@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if(requestCode==JUMP_TO_TARGET && requestCode == RESULT_OK){router(getIntent().getData());getIntent().setData(null);}
}private void router(Uri uri) {}
复制代码

通过上面两部分的处理,基本能够满足APP“死亡”的情况下,先跳转闪屏的需求。

作者:看书的小蜗牛 原文链接:被后台杀死后,Android应用如何重新走闪屏逻辑

仅供参考,欢迎指正

被后台杀死后,Android应用如何重新走闪屏逻辑相关推荐

  1. Android应用启动时白色闪屏原因及解决办法

    白色闪屏现象: 如果OnCreate().onStart().onResume()中操作太多,耗时较久.那么就会在主界面显示出来之前出现白色闪屏.为了更清晰的看出白色闪屏,这里在代码中执行50000次 ...

  2. centos 开机选完 grub 后左上角一个 _ 还一直闪屏

    1. 现象描述 R 系的国产操作系统,服务器开机之后,到选完 grub 后,左上角出现一个 '_' 并且一直闪屏,服务器没死机,键盘鼠标没掉电 2. 初步分析 可能是 boot 损坏,或是图形化没有启 ...

  3. Android Home键引起的闪屏问题

    场景: 当点击App图标的时候会出现闪屏页,如果按下Home键,再次点击App图标,应该直接进入登录页或者主界面,而不是再次出现闪屏页. 实现代码,在配置文件<action android:na ...

  4. Android 页面跳转时闪屏问题

    界面间来回跳转,Activity之间跳转或者Fragment跳转Activity出现闪屏问题

  5. Android后台杀死系列之一:FragmentActivity及PhoneWindow后台杀死处理机制

    App在后台久置后,再次从桌面或最近的任务列表唤醒时经常会发生崩溃,这往往是App在后台被系统杀死,再次恢复的时候遇到了问题,而在使用FragmentActivity+Fragment的时候会更加频繁 ...

  6. Android 后台杀死及恢复的机制

    App在后台久置后,再次从桌面或最近的任务列表唤醒时经常会发生崩溃,这往往是App在后台被系统杀死,再次恢复的时候遇到了问题,而在使用FragmentActivity+Fragment的时候,经常会遇 ...

  7. android 闪屏引导,启动体验设计-闪屏,启动页,引导页

    冷启动(cold start) 冷启动是指应用尚未运行,系统创建进程并初始化应用. 热启动是指应用已经运行但是在后台被挂起,从后台恢复应用. 冷启动时间稍微会长一点,在此期间可能会看到白屏或黑屏或感受 ...

  8. Android如何接入渠道SDK的闪屏页?一个activity就够了

    如果你是做SDK开发的,应该接入过很多渠道SDK,常见的渠道有华为.小米.VIVO.OPPO.应用宝.UC九游.三星.小七等,还有一些小的渠道以及一些聚合渠道SDK,成千上万个渠道,其中部分渠道是需要 ...

  9. Android闪屏页适配

    Android闪屏页适配 首先,为了避免第一次打开出现白屏,所以应该自定义style,添加anroid:windowBackground属性.此属性下放了一张1080*1920的闪屏图片,会出现在不同 ...

  10. activity 变成后台进程后被杀死_Android后台杀死系列之二:ActivityManagerService与App现场恢复机制...

    本篇是Android后台杀死系列的第二篇,主要讲解ActivityMangerService是如何恢复被后台杀死的进程的(基于4.3 ),在开篇FragmentActivity及PhoneWindow ...

最新文章

  1. 机器学习(MACHINE LEARNING) 【周志华版-”西瓜书“-笔记】 DAY6-支持向量机
  2. Ubuntu Android Studio/IntelliJ IDEA 支持文件中文命名
  3. mysql配置不成功_mysql 5.7.17 zip安装配置教程 mysql启动失败的解决方法
  4. 多元高斯分布(Multivariate Gaussian Distribution)
  5. C语言 strlen 函数 - C语言零基础入门教程
  6. 积分图像追踪目标 (一)
  7. 多媒体计算机的扫描仪属于感觉媒体吗,多媒体计算机中的扫描仪属于感觉媒体...
  8. Speex manul中文版
  9. 暴力破解rar和zip加密压缩包
  10. 2022-2028年中国沉香行业发展模式分析及投资趋势预测报告
  11. 10938 - Flea circus
  12. Proactol什么是脂肪燃烧
  13. BODIPY-TR氟化硼二吡咯偶联神经酰胺/炔烃/氨基/羧基等活性基团
  14. 软件工程团队队名_软件工程团队负责人的角色是什么
  15. 2022-11-08 Python基础知识 2
  16. wcp mysql 密码_[wcp部署]Linux(Ubuntu)安装部署WCP
  17. 基于SSM在线学习网站包含课程管理-错题-收藏-考试测试-学生教师管理员58198(idea-javaweb-javaee-j2ee-springboot)
  18. AdvancedInstaller打包工具使用(五)
  19. 【FPGA】SCCB通信协议
  20. linux轻量级web浏览器,QupZilla 1.8.6 发布,轻量级Web浏览器

热门文章

  1. 视觉注意力的循环神经网络模型(Recurrent Models of Visual Attention)
  2. TED如何掌控你的时间(第二天)
  3. USGS批量下载SRTM1数据
  4. unity 改变ui文字_如何在Unity中实现逐字打印UI中的Text文字
  5. 实习成长之路:MySQL五:全局锁和表锁 :给表加个字段怎么有这么多阻碍?
  6. linux java部署tomcat_Linux 使用脚本安装Tomcat并部署程序
  7. java insert 返回主键_MyBatis中insert操作返回主键的实现方法 – java – www.cfei.net
  8. flutter系列之flutter工程结构详解(android视角)
  9. webStrom 开始你的第一个React应用
  10. python标准库——time模块