Activity 生命周期

Android官方文档和其他不少资料都对Activity生命周期进行了详细介绍,在结合资料和项目开发过程中遇到的问题,本文将对Activity生命周期进行一次总结。

Activity是由Activity栈进管理,当来到一个新的Activity后,此Activity将被加入到Activity栈顶,之前的Activity位于此Activity底部。Acitivity一般意义上有四种状态:

1.当Activity位于栈顶时,此时正好处于屏幕最前方,此时处于运行状态

2.当Activity失去了焦点但仍然对用于可见(如栈顶的Activity是透明的或者栈顶Activity并不是铺满整个手机屏幕),此时处于暂停状态

3.当Activity被其他Activity完全遮挡,此时此Activity对用户不可见,此时处于停止状态

4.当Activity由于人为或系统原因(如低内存等)被销毁,此时处于销毁状态;

在每个不同的状态阶段,Adnroid系统对Activity内相应的方法进行了回调。因此,我们在程序中写Activity时,一般都是继承Activity类并重写相应的回调方法。

Activity 生命周期

图中详细给出了Activity整个生命周期的过程,以及在不同的状态期间相应的回调方法。

图中需要注意一下几点:

1.Activity实例是由系统自动创建,并在不同的状态期间回调相应的方法。一个最简单的完整的Activity生命周期会按照如下顺序回调:onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy。称之为entire lifetime。

2.当执行onStart回调方法时,Activity开始被用户所见(也就是说,onCreate时用户是看不到此Activity的,那用户看到的是哪个?当然是此Activity之前的那个Activity),一直到onStop之前,此阶段Activity都是被用户可见,称之为visible lifetime。

3.当执行到onResume回调方法时,Activity可以响应用户交互,一直到onPause方法之前,此阶段Activity称之为foreground lifetime。

在实际应用场景中,假设A Activity位于栈顶,此时用户操作,从A Activity跳转到B Activity。那么对AB来说,具体会回调哪些生命周期中的方法呢?回调方法的具体回调顺序又是怎么样的呢?

开始时,A被实例化,执行的回调有A:onCreate -> A:onStart -> A:onResume。

当用户点击A中按钮来到B时,假设B全部遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。

此时如果点击Back键,将依次执行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。

至此,Activity栈中只有A。在Android中,有两个按键在影响Activity生命周期这块需要格外区分下,即Back键和Home键。我们先直接看下实验结果:

此时如果按下Back键,系统返回到桌面,并依次执行A:onPause -> A:onStop -> A:onDestroy。

此时如果按下Home键(非长按),系统返回到桌面,并依次执行A:onPause -> A:onStop。由此可见,Back键和Home键主要区别在于是否会执行onDestroy。

此时如果长按Home键,不同手机可能弹出不同内容,Activity生命周期未发生变化(由小米2s测的,不知道其他手机是否会对Activity生命周期有影响)。

由于Android本身的特性,使得现在不少应用都没有直接退出应用程序的功能,按照一般的逻辑,当Activity栈中有且只有一个Activity时,当按下Back键此Activity会执行onDestroy,那么下次点击此应用程图标将从重新启动,因此,当前不少应用程序都是采取如Home键的效果,当点击了Back键,系统返回到桌面,然后点击应用程序图标,直接回到之前的Activity界面,这种效果是怎么实现的呢?

通过重写按下Back键的回调函数,转成Home键的效果即可。

@Overridepublicvoid onBackPressed() {

Intent home =new Intent(Intent.ACTION_MAIN);

home.addCategory(Intent.CATEGORY_HOME);

startActivity(home);

}

当然,此种方式通过Home键效果强行影响到Back键对Activity生命周期的影响。注意,此方法只是针对按Back键需要退回到桌面时的Activity且达到Home效果才重写。

或者,为达到此类效果,Activity实际上提供了直接的方法。

1activity.moveTaskToBack(true);

moveTaskToBack()此方法直接将当前Activity所在的Task移到后台,同时保留activity顺序和状态。

在之前的项目开发过程中,当时遇到一个很奇怪的问题:手机上的“开发者选项”中有一个“不保留活动”的设置,当开启此设置,手机上的设置提示是“用户离开后即销毁每个活动”,开启后,对于其他的应用程序是从A Acticity到B Activity,然后Back键回到A,此时,其他应用程序只是先白屏(有可能黑屏等,取决于主题设置)一下,然后A开始可见,但是我的应用程序中出现的一个结果却是直接返回到了桌面。一开始百思不得其解。最后终于定位出问题。首先,我们需要明确开启此设置项后对Activity生命周期的影响。开启此设置项后,当A到B时,假设B全部遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop -> A:onDestroy。是的,A在系统原本的生命周期回调中增加了onDestroy。此即“用户离开后即销毁每个活动”的含义。但此时需要注意的是,只要没有认为的调用A的finish()方法,虽然A执行了onDestroy,但Activity栈中依然保留有A,此时B处于栈顶。那么在B中按Back键回到A时,将依次执行:B:onPause -> A:onCreate -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。没错,A从onCreate开始执行了。此处也就解释了为什么A可能会出现白屏(或黑屏等)一下的原因了。

那么为什么我的应用程序会跟其他应用程序出现不一样呢?最后定为出问题在于当时我的应用程序中为了做到完全退出应用程序效果,专门使用了一个Activity栈去维护Activity(当时是借鉴了网上的此类实现方案,现在想想,实在没必要,且不说Android本身特性决定了没必要通过如此方法去达到退出效果,仅仅是此方法本身也存在很大的问题,现在在网上依然能见到有不少文章说到应用程序退出可以使用此方法,哎。。),在onCreate中入栈,onDestroy出栈,调用了如下方法

1// 结束Activity&从堆栈中移除2AppManager.getAppManager().finishActivity(this);

其中,AppManager中finishActivity函数具体定义是:

1/** 2 * 结束指定的Activity 3/ 4publicvoid finishActivity(Activity activity) { 5if(activity !=null) { 6 activityStack.remove(activity); 7* activity.finish();** 8activity =null; 9 }10}

至此,相信大家应该看出问题的所在了吧。

没错,问题在于执行了activity的finish()方法!! activity的finish()方法至少有两个层面含义,1.将此Activity从Activity栈中移除,2.调用了此Activity的onDestroy方法。对于不开启“不保留活动”的设置项,实际上也没什么影响,但是一旦开启此设置,问题显露无疑。开启此此设置后,正常情况下离开A,即使执行了A的onDestroy,Activity栈中还是有A的,但是我这样写后,finish()方法一执行,Activity栈中就没有A了,因此,当点击Back键时,Activity栈中已经没有此应用的任何Activity了,直接来到了手机桌面。

可能,有些人会说,我就是要通过此种方法想去完全退出应用程序,同时希望自己的Activity栈和系统中Activity栈保持一致,怎么办呢?

在此,可以通过如下改写去实现:

/*** 结束指定的Activity

*/publicvoid finishActivity(Activity activity) {

if(activity !=null) {

// 为与系统Activity栈保持一致,且考虑到手机设置项里的"不保留活动"选项引起的Activity生命周期调用onDestroy()方法所带来的问题,此处需要作出如下修正if(activity.isFinishing()){

    activityStack.remove(activity);

    //activity.finish();activity =null;

}

}

}

面试题
(1)初始化中OnCreate与OnResume的区别
oncreate 和 onresume 在第一次创建的时候都会执行。但是实际上 oncreate 和 onresume 的确有区别。
oncreate 是当被创建的时候执行, onresume 是被展示的时候执行。比如在栈式管理的方式下,如果不被销毁,那么oncreate 只会被执行一次, 而 onresume是依照展示机会执行。有人说说 oncreate 里面初始化不变的控件, onresume 里面初始化变的控件,这个也许你执行没有问题,但是这么想的时候已经错了。因为 oncreate 就代表了初始化。 所以所有的控件都要在 oncreate 里面初始化。onresume 里面去执行初始化后被展示的时候要进行的行为操作。
(2)Android的Activity什么时候会调用onCreate()而不调用onStart()?
我们在onCreate()里面加了super.onStop();或super.onDestroy();,这样执行到onCreate()函数时,执行流程是这样的:onCreate -> onStop或onDestroy -> onStart -> onResume。最终还是会执行onStart。而如果加上finish(),则onCreate -> onDestroy,而不会执行onStart。

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

推荐阅读更多精彩内容