Android四大组件之Activity

有关Activity介绍的文字实在是太多了,本着对Android开发基础知识进行查漏补缺的原则,还是将这部分的知识梳理成了这篇文章。

Activity作为Android中最为重要的组件,在汉语中似乎一直没有合适的词语表达。Activity是“界面展示”+“后台逻辑”的结合,用“活动”一词对这一组件进行描述实在是太牵强啦。因此,本文仍然使用Activity来指代这一组件吧。本文从生命周期和启动模式两个部分总结了Activity相关的知识点。


一、 Activity的生命周期

都闪开,首先还是官方文档中那张熟悉得不能再熟悉的生命周期流程图:


虽然图中未列出,Activity在与用户进行交互的过程中,在如下四种状态之间互相切换:

Running: Activity正处于Activity栈最顶端,与用户正在进行交互。(完全可见)

Paused:与Running状态不同,Activity此时未完全显示出来,例如被一个dialog或者透明的Activity所部分遮盖,无法与用户交互,但仍然保持着状态信息数据。(部分可见)

Stopped:当Activity被其他Activity完全覆盖不可见,此时不再处于Activity栈顶端。(完全不可见)

Destroyed:当Activity被系统回收或者被用户关闭,则会被系统销毁掉。

如图所示在这四种状态的切换过程中,系统将会回调不同的方法:

onCreate():该方法在Activity第一次被创建的时候被回调,我们通常在该方法中进行一些静态初始化工作,例如加载页面布局,创建View,绑定数据等等。

onStart():在Activity被启动或重新启动过程中会调用该方法。

onResume():在Activity能够与用户交互之前调用此方法。我们通常会在该方法中初始化并打开一些独占设备,例如相机,重新初始化在onPause方法中释放的资源等。

onPause():当系统开始调用其他Activity时会回调此方法。我们通常会在其中释放那些在onResume中打开的资源,确认对持久性数据的未保存更改、停止动画、释放sensor,reciever,ContentProvider保存数据,以及其他可能消耗 CPU 的内容。需要注意的是这里进行的操作不能太耗时,因为它返回后,下一个 Activity 才能继续执行。该方法与onResume方法相对应,这两对方法从Activity是否可交互的角度来回调的。

onStop():当系统要停止或覆盖该Activity时会回调此方法,此时Activity已经不可见了,该方法与onStart方法相对应,这两对方法是从Activity是否可见的角度来回调的。

onRestart():当Activity未被完全销毁掉,需要重新启动该Activity时候将会在onStop和onStart方法之间回调该方法。

onDestroy():当系统要销毁掉Activity前会调用该方法。无论是Activity是人为finish掉还是系统由于资源短缺而回收,都会回调该方法。这里可以进行一些资源释放和回收工作。

上述方法的回调顺序都是在Activity处于正常的生命周期内,而当Activity配置发生改变或系统资源紧张对Activity进行了回收时,Activity则会被销毁,抑或重新创建。为了应对Activity非正常生命周期内的情况,系统使用了onSaveInstanceState和onRestoreInstanceState两对方法来完成对Activity状态信息和数据的存储和恢复。这对方法在Activity正常的生命周期中是不会被调用的,只有当资源不足或配置改变而导致的异常销毁重建时才会调用。

在这两个方法中,系统自动做了一定的存储和恢复工作,我们也可以将我们需要保存的数据存于Bundle中,从而保证我们Activity的强壮性。


二、 Activity的任务栈和启动模式

Android系统采用了栈结构来组织和存储Activity实例对象集合,这样的栈结构被称为任务栈(Task Stack)。一个任务栈中的Activity可以来自不同的App,而同一个App的不同Activity也可以存在于不同的任务栈中。栈结构采用FIFO的组织模式,当前正与用户交互的Activity位于栈顶,该任务栈也位于前台。

为了满足开发中的各种特殊需求,Activity可以采用四种模式完成启动:

standard 默认的启动模式。每次都要新创建Activity的实例对象,然后进入原Activity所在的的任务栈,覆盖在原Activity之上。(在这种启动模式下,哪个Activity启动了新的Activity,那么这个新的Activity就运行在哪个Activity所在任务栈中。)

singleTop 栈顶复用模式。在这种启动模式下,如果当前任务栈顶的Activity与要启动的Activity相同,则不创建新的的Activity对象(自然也不会回调生命周期中的方法),而是复用当前栈顶的Activity对象,但仍然会调用onNewIntent()方法。如果栈顶Activity与要启动的Activity不同,则创建新的Activity实例对象,并入栈。这种启动模式通常用于接收消息点击后所显示的Activity。

singleTask 栈内复用。在这种启动模式下,系统首先判断当前任务栈中是否存在要启动的Activity实例对象。如果当前栈中已经存在该Activity实例对象,则覆盖在该Activity实例对象之上的Activity都要出栈并销毁,从而复用已经存在的Activity对象,但仍然会调用onNewIntent()方法。使用该模式时请注意Activity所要运行的任务栈,该模式具有创建不存在的任务栈的作用。

另外有一点需要注意的是,当所启动的Activity实例对象并未位于当前任务栈,而是位于后台任务栈中,则该后台任务栈中的Activity实例对象都被切换到前台任务栈中,并仍按原栈中顺序组织和存储。

singleInstance 单例模式。使用该模式启动的Activity,系统为该Activity新建一个任务栈来运行,从而可以满足多个应用共享该Activity实例的需求。

在Activity实例对象的创建和启动过程中,系统必然要通过某种方式指定是所启动的Activity实例对象,以及该对象所属的任务栈。通常情况下,Activity  A所启动了Activity B,如无特殊指定,系统会将B运行于A所属的任务栈中。

Android系统使用TaskAffinity参数标识了该Activity对象期望所属的任务栈(默认为该app的包名),仅仅是期望,而不是一定要运行在该任务栈中,如果该任务栈还不存在,未必会创建该任务栈(singleTask和singleInstance模式会创建)。singleTask这种栈内复用模式就是在TaskAffinity所指定的栈内进行复用。TaskAffinity参数通常与allowTaskReparenting结合使用。

我们可以通过manifest文件和Intent Flag两种方式来指定Activity的启动模式,前者的优先级低于后者。常用的Intent Flag包括以下几种方式:

Intent.FLAG_ACTIVITY_NEW_TASK:新创建一个任务栈来运行Activity,通常用于service启动Activity的场景。

Intent.FLAG_ACTIVITY_SINGLE_TOP:以singleTop模式启动Activity。

Intent.FLAG_ACTIVITY_CLEAR_TOP:通常与Intent.FLAG_ACTIVITY_NEW_TASK相结合使用,达到singleTask模式的效果。

Intent.FLAG_ACTIVITY_NO_HISTORY:以该模式启动的Activity,当该Activity启动其他Activity后就会被销毁掉,不存储于任务栈中。

另外,我们还可以在manifest文件中指定clearTaskOnLaunch属性,保证每次返回该Activity时,其上的Activity都被清除掉,从而保证该Task每次初始化时都只有这个一个Activity。


Note:

良好的编程习惯:在你负责开发的activity中加入启动该activity的方法。


参考书目:

 Android官方文档

《Android群英传》 作者:徐宜生

《Android开发艺术探索》 作者:任玉刚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容