TWT Studio - Android 组培训 & 技术分享

Android Activity生命周期 超详解

2018-10-27  本文已影响382人  吃啥呀

生命周期 四大启动模式 标识位 Task栈 Android


1.初识 Activity

2.Android 任务栈( Task )

浅显理解:

  • 打开一个新的Activity ---> 在任务栈的结构中添加一个Activity组件
  • 退出当前Activity ---> 任务栈的结构中减少一个Activity组件
  • 一个任务栈包含了一个activity的集合

android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:
只有在任务栈栈顶的activity才可以跟用户进行交互(这里的交互就是指点击、输入文字等操作)

启动一个Application的时候,系统会为它默认创建一个对应的Task,用来放置根Activity(应用程序启动的第一个Activity)。默认启动Activity会放在同一个Task中,新启动的Activity会被压入启动它的那个Activity的栈中,并且显示它。当用户按下回退键时,这个Activity就会被弹出栈,按下Home键回到桌面,再启动另一个应用,这时候之前那个Task就被移到后台,成为后台任务栈,而刚启动的那个Task就被调到前台,成为前台任务栈,Android系统显示的就是前台任务栈中的Top实例Activity。
ps :activity还有其他启动方式,在文章末尾介绍

有的Activity,虽然不在同一个app中,但为了保持用户操作的连贯性,把他们放在同一个任务(Task)中。
例如,在我们的应用中的一个Activity A中点击发送邮件,会启动邮件程序的一个Activity B来发送邮件,这两个activity是存在于不同app中的,但是被系统放在一个任务(Task)中,这样当发送完邮件后,用户按back键返回,可以返回到原来的Activity A中,这样就确保了用户体验。

3. Activity的四种形态

状态名 解释 状态
Active/Running 运行状态:位于栈顶,正好处于屏幕最前方 可见+可交互
Paused 暂停状态:失去了焦点,不能与用户交互,但仍然可见(比如栈顶的 Activity是透明或没有铺满屏幕) 可见+不可交互
Stopped 停止状态:对用户不可见,也不能交互 不可见+不可交互
Killed 销毁状态:由于人为或者系统原因被销毁 不可见+不可交互

在每个状态,Android 系统对 Activity 都写了相应的回调方法。因此,我们在程序中写 Android时,一般都是继承 Activity 时,一般都是继承 Acitivity 类并重写相应的回调方法

4. Activity的生命周期

4.1 Activity的正常一生

oncreate()->onstart()->onResume()->onRestart()->onPouse()->onStop()->onDestory()

onCreat() : 当我们点击activity的时候,系统会调用activity的oncreate()方法,在这个方法中我们会初始化当前布局setContentLayout()方法。
onStart():onCreate()方法完成后,此时activity进入onStart()方法,当前activity是用户可见状态,但没有焦点,与用户不能交互,一般可在当前方法做一些动画的初始化操作
onResume():onStart()方法完成之后,此时activity进入onResume()方法中,当前activity状态属于运行状态 (Running),可与用户进行交互。
onPause():当另外一个activity覆盖当前的acitivty时([1]启动了一个新的Activity [2]返回上一个Activity),此时当前activity会进入到onPause()方法中,当前activity是可见的,但不能与用户交互状态。通常情况下onPause()函数不会被单独执行,执行完onPause()方法后会继续执行onStop()方法。
onStop():onPause()方法完成之后,此时activity进入onStop()方法,此时activity对用户是不可见的,在系统内存紧张的情况下,有可能会被系统进行回收。所以一般在当前方法可做资源回收。(ps:只要activity还可见,就不会调用onStop,比如下一个开启的activity是完全透明度)
onDestory():onStop()方法完成之后,此时activity进入到onDestory()方法中,结束当前activity。
执行完onDestory()方法的Activity接下来面对的是被GC回收,宣告生命终结。
onRestart():当用户在其他的Activity或者桌面回切到这个Activity时,这个Activity就会先去执行onRestart()函数。调用顺序onPause()->onStop()->onRestart()->onStart()->onResume().

Activity 的生命周期.png

onCreate和onDestory是配对的,分别标识着Activity的创建和销毁,并且只可能有一次调用。
从Activity是否可见来说,onStart和onStop是配对的,随着用户的操作或者设备屏幕的点亮和熄灭,这两个方法可能被调用多次;
从Activity是否在前台来说,onResume和onPause是配对的,Activity位于其他 Activity 之前,可与用户交互并具有输入焦点。

生命周期和状态.png
4.2 Acitivity的异常生命周期

当Activity处于竖屏状态,如果突然旋转屏幕,由于系统配置发生了变化,在默认的情况下,Activity会被销毁并重新创建,当然我们可以人为干预来防止这种情况。
这里有点需要特别注意,onSaveInstanceState和onRestoreInstanceState只有在Activity异常终止时才会被调用的,正常情况是不会调用这两个方法的。

5. Android的进程层次

activity的进程优先级:前台进程>可见进程>service进程>后台进程>空进程

进程层次.png
5.1 前台进程

当前进程activity正在与用户进行交互。
当前进程service正在与activity进行交互或者当前service调用了startForground()属于前台进程或者当前service正在执行生命周期(onCreate(),onStart(),onDestory())
进程持有一个BroadcostReceiver,这个BroadcostReceiver正在执行onReceive()方法

5.2 可见进程

进程持有一个activity,这个activity不再前台,处于onPouse()状态下,当前覆盖的activity是以dialog形式存在的。
进程有一个service,这个service和一个可见的Activity进行绑定。

5.3 service进程

当前开启startSerice()启动一个service服务就可以认为进程是一个服务进程。

5.4 后台进程

activity的onStop()被调用,但是onDestroy()没有调用的状态。该进程属于后台进程。

5.5 空进程

进程没有任何运行的数据了,且保留在内存空间,并没有被系统killed,属于空进程。该进程很容易被杀死。

6. Activity 的四种启动模式

6.1 Standard 模式

标准模式,也是系统的默认模式(可以不指定),在这样模式下,每启动一个Activity都会重新创建一个Activity的新实例,并且将其加入任务栈中,而且完全不会去考虑这个实例是否已存在。

Standard.png
6.2 singleTop 模式

栈顶复用模式,顾名思义,在这种模式下,如果有新的Activity已经存在任务栈的栈顶,那么此Activity就不会被重新创建新实例,而是复用已存在任务栈栈顶的Activity。这里重点是位于栈顶,才会被复用,如果新的Activity的实例已存在但没有位于栈顶,那么新的Activity仍然会被重建。

isingleTop1.png

当需要新创建的MainActivity位于栈顶时,MainActivity并没有重新创建。下面我们再来看看新创建的MainActivity没有位于栈顶的情况。

singleTop2.png

嗯,这就是singTop模式。这种模式通常比较适用于接收到消息后显示的界面,如qq接收到消息后弹出Activity界面,如果一次来10条消息,总不能一次弹10个Activity,是吧?再比如新闻客户端收到了100个推送,你每次点一下推送他都会进入某个activiy界面(显示新闻只用一个activity,只是内容不同而已),这时也比较适合使用singleTop模式。

6.3 singleTask 模式

栈内复用模式。这是一种单例模式,与singTop点类似,只不过singTop是检测栈顶元素是否有需要启动的Activity,而singTask则是检测整个栈中是否存在当前需要启动的Activity,如果存在就直接将该Activity置于栈顶,并将该Activity以上的Activity都从任务栈中移出销毁,同时也会回调onNewIntent方法。情况如下图:

singleTask.png

从图中可以看出,当我们再次启动MainActivity时,由于MainActivity位于栈中,所以系统直接将其置于栈顶,并移除其上方的所有Activity。当然如果所需要的MainActivity不存在栈中,则会创建新的Activity并添加到栈中。singleTask 模式比较适合应用的主界面activity(频繁使用的主架构),可以用于主架构的activity,(如新闻,侧滑,应用主界面等)里面有好多fragment,一般不会被销毁,它可以跳转其它的activity 界面再回主架构界面,此时其他Activity就销毁了。当然singTask还有一些比较特殊的场景这个我们后面会一一通过情景代码分析。

6.4 singleInstance 模式

在singleInstance模式下,该Activity在整个android系统内存中有且只有一个实例,而且该实例单独尊享一个Task。换句话说,A应用需要启动的MainActivity 是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A单独在这个新的任务栈中,如果此时B应用也要激活MainActivity,由于栈内复用的特性,则不会重新创建,而是两个应用共享一个Activity的实例。如下图所示:

singleInstance.png

从图中我们可以看到最终AB应用都共享一个singleInstance模式的MainActivity,也没有去重新创建。

ps :启动 Activity 时,先看是否已经存在它需要的栈,没有则创建一个空栈,再在该栈中添加该 Activity 组件。比如在标准模式下,点开 app,启动根 Activity,是没有已经存在的栈,就创建一个栈,并向该栈中添加根 Activity 组件,此时再从根 Activity 启动另一个 ActivityB,对于B来说已经它需要的栈(即刚才存放根 Activity 的栈),就不用再重新创建栈了。但是如果将 ActivityB 的启动模式改成singleInstancce,则需要再重新创建一个栈

7.设置 Activity 的启动方式

7.1通过AndroidMenifest.xml文件为Activity指定启动模式
<activity android:name=".ActivityC" 
          android:launchMode="singleTask" />
7.2 通过在Intent中设置标志位(addFlags方法)来为Activity指定启动模式

Intent.FLAG_ACTIVITY_SINGLE_TOP 该标志位表示使用singleTop模式来启动一个Activity,与在清单文件指定android:launchMode="singleTop"效果相同。
Intent.FLAG_ACTIVITY_CLEAR_TOP 该标志位表示使用singleTask模式来启动一个Activity,与在清单文件指定android:launchMode="singleTask"效果相同。
Intent.FLAG_ACTIVITY_NO_HISTORY 使用该模式来启动Activity,当该Activity启动其他Activity后,该Activity就被销毁了,不会保留在任务栈中。如A-B,B中以这种模式启动C,C再启动D,则任务栈只有ABD。
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 使用该标识位启动的Activity不添加到最近应用列表,也即我们从最近应用里面查看不到我们启动的这个activity。与属性android:excludeFromRecents="true"效果相同。

Intent intent = new Intent();
intent.setClass(ActivityB.this,ActivityA.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

第2种指定方式的优先级高,同时存在时,以第2种为准。

思考问题

ABCD四个Activity的启动模式均为SingleTask。此时,先启动CD再启动AB,之后由B启动D。请问现在的后退列表是什么样子的?

situation1.png

按照DCBA的顺序退出

result1.png

ABCD四个Activity的启动模式均为SingleTask。此时,先启动CD再启动AB,之后由B启动C。请问现在的后退列表是什么样子的?

situation2.png

按照CBA的顺序退出

result2.png
上一篇下一篇

猜你喜欢

热点阅读