当用户再次启动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();
if(uri!=null){
SplashActivity.startActivityForResult(this,JUMP_TO_TARGET)
}
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://i-blog.csdnimg.cn/blog_migrate/f8b4d5d2a3637d4789ad8d7b45dc378c.jpeg)
结尾
好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。
这里放上一部分我工作以来以及参与过的大大小小的面试收集总结出来的一套进阶学习的视频及面试专题资料包,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家~
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
48587144)]
[外链图片转存中…(img-S7eUcLh1-1713248587146)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!