Activity不同情况下生命周期

想要彻底弄清楚Activity在不同情况下的生命周期需要先掌握Activity的一些基础知识

Activity完整的生命周期如下图:


知道了Activity完整的生命周期之后还需要知道Activity的启动模式。

Activity四种启动模式:

standard:

默认的启动模式,每次通过这种模式启动目标Acitivity,都创建一个新的实例,并将该Activity添加到当前栈顶。

singleTop:

只有当Activity位于栈顶时,系统才不会重新创建目标Activity的实例,而是直接复用已有的Activity实例。否则创建一个新的实例。这种模式经常被用在新闻展示页,当推送过来一条新闻,跳转到新闻页显示,如果你正在看新闻,就不需要重复的创建这个activity

singleTask:

如果栈中不存在目标Activity时,则创建目标Activity实例。

如果栈中存在目标Activity时,

(1)已经位于栈顶,此时与singleTop行为相同

(2)不位于栈顶,系统会使该Activity上面所有的Activity出栈。

singleInstance:

如果栈中不存在目标Activity,系统会创建一个新的任务栈,再创建Activity实例,将它加入该栈中

如果栈中存在该Activity,无论哪个应用程序调用,都不会创建新的Activity

---------------------

举例

假设有两个Activity A、B

standard模式

当A启动到从A跳转到B的生命周期

A启动时:onCreate -> onStart -> onResume

从A跳转到B时:A.onPause -> B.onCreate -> onStart -> onResume -> A.onStop

按back键返回时:B.onPause -> A.onReStart -> onStart -> onResume -> B.onStop -> onDestroy

singleTop模式

设定A为singleTop,启动A,从A跳A,就是在栈顶时会不会创建A的实例

A启动时:onCreate -> onStart -> onResume

从A跳A时:onPause -> onResume

按back键返回时:onPause -> onStop -> onDestroy

可以看到并没有重新创建A的实例,只是执行了onPause 和onResume

singleTask模式

设定A为singleTask,启动A,从A跳B,再从B跳A

A启动时:onCreate -> onStart -> onResume

从A跳转到B时:A.onPause -> B.onCreate -> onStart -> onResume -> A.onStop

从B跳转到A时:B.onPause -> A.onReStart -> onStart -> onResume -> B.onStop -> onDestroy

可以看到当A在栈中存在时,再次跳转不会创建A的实例并使A上面的B出栈

singleInstance模式

为 singleInstance 模式时,activity独占一个task,现在有以下三个activity: Act1、Act2、Act3,其中Acti2 为 singleInstance 模式。它们之间的跳转关系为: Act1 – Act2 – Act3 ,现在在Act3中按下返回键,由于Act2位于一个独立的task中,它不属于Act3的上下文activity,所以此时将直接返回到Act1,Act1再按下返回键时到Act2,这就是singleInstance模式。


看完四种模式,这里会有疑问:

为什么要先执行A的onPause方法,再执行B的生命周期方法? 

为什么不是执行完A的onStop方法之后再执行B的生命周期方法?

首先来看第一个问题,假如A正在播放一段音乐,如果先执行B的生命周期,再执行A的onPause方法,就会出现B已经显示出来,A中的音乐还在播放的异常情况。而如果先执行了A的onPause方法,我们就可以在其中执行一些操作来暂停音乐的播放。原本onPause方法的设计职责即使如此。

对于第二个问题,由于Activity的可见生命周期是onStart()到onStop(),假如先执行A的onPause()和onStop(),再执行B的生命周期,每次切换的时候就会出现黑屏的情况,这种切换效果显然是不优雅的。

注:

建议在onCreate()中调用setContentView()、findViewById()

建议在onResume()中打开独占设备(比如相机)、开启动画等

建议在onPause()中执行关闭独占设备、停止动画等比较耗CPU的操作,但不要执行比较耗时的操作,底层执行Activity的onPause()时,有一定的时间限制的,当ActivityManagerService通知应用进程暂停指定的Activity时,如果对应的onPause()在500ms内还没有执行完,ActivityManagerService就会强制关闭这个Activity。

onStop()中可以执行一些比较耗时的操作,这是在后台执行所以也不影响用户的体验

附:

伴随着activity常用的除了生命周期还有两个方法,onSaveInstanceState 和 onNewIntent

1.onSaveInstanceState

我们都知道不同的手机,内存不同,系统在内存不足的时候很有可能就会把你APP中不再栈顶的activity给回收掉。如果这个activity无关紧要那就啥也不说了,但是就怕它对你来说很重要。这个时候你不对它进行保护措施的话,你就等着哭吧。比如你打开了A,A是一个注册类activity。然后你填写了一堆信息后,返回桌面去看了一条短信,或者接了一个电话,等你再打开这个的时候你发现里面填写的东西都不见了,这个时候你想不想一巴掌拍死这个开发人员?

所以呢onsaveinstancestate()就可以闪亮登场了,虽然你也可以使用其他保存机制去处理,但是对于这种情况,onsaveinstancestate()依然是最佳的选择。onsaveinstancestate()方法有的同学有可能没见过 但是savedinstancestate相必都见过,就是在oncreate()方法的那个括号里面,savedinstancestate是一个bundle类型的参数,bundle有很多保存数据的方法这个你想必是知道的吧,对我们就是利用这个去保存数据。onsaveinstancestate()回调方法会保证一定在activity被回收之前调用

onSaveInstanceState方法会在什么时候被执行,有这么几种情况:

当用户按下HOME键时。

长按HOME键,选择运行其他的程序时。

按下电源按键(关闭屏幕显示)时。

从activity A中启动一个新的activity时。

屏幕方向切换时,例如从竖屏切换到横屏时。

当按下HOME键或者锁屏时,会执行onPause -> onSaveInstanceState -> onStop

当从activity A跳转到 B 时,A.onPause -> B.onCreate -> onStart -> onResume -> A.onSaveInstanceState -> A.onStop

使用:

@Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_one);

        if (savedInstanceState != null) {

            String oldString = savedInstanceState.getString("Activity");

            Log.e(TAG,"oldString="+oldString);

        }

        Log.e(TAG,"onCreate");

    }

@Override

    protected void onSaveInstanceState(Bundle outState) {

        super.onSaveInstanceState(outState);

        Log.e(TAG,"onSaveInstanceState");

        String string = "activity 被系统回收了怎么办?";

        outState.putString("Activity", string);

    }


2.onNewIntent

如果activity设置为singleTask或者signleTop模式【当调用startActivity方法时,这两种模式不会重新创建activity,只会调用onNewIntent方法,当然任务栈中没有销毁该activity的情况下】,再向activity传值时,就可以利用onNewIntent

执行顺序:onNewIntent -> onReStart -> onStart -> onResume

@Override

    protected void onNewIntent(Intent intent) {

        super.onNewIntent(intent);

        Log.e(TAG,"onNewIntent");

        setIntent(intent);

        String msg = getIntent().getExtras().getString("msg");

        Log.e(TAG,"msg="+msg);

    }

//另一个activity中发送

Intent intent = new Intent(this,OneActivity.class);

intent.putExtra("msg","传值过来");

startActivity(intent);

---------------------

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

推荐阅读更多精彩内容