activity两种情况下的生命周期分析

趁着最近没什么项目,打算回顾整理下android的基础知识,算是查漏补缺。

关于Activity的生命周期,参看了相关书籍(android开发艺术探索)和文档,还是对以前的知识体系有了很大程度的改善的,在这里记录一下。

1、典型情况下的生命周期

典型情况,指有用户参与的情况下,Activity所经过的生命周期的改变。
首先是经典的生命周期图:

Paste_Image.png

1.1、首先介绍下几种状态:

1)Created:刚刚完成一些初始化操作,Activity未可见。
2)Started:Activity可见,但还在还没出现在前台。
3)Resumed:Activity可见,且在前台。(可视,可接受输入,可执行代码)
4)Paused:(部分可视,不可接受输入,不可执行代码)
5)Stopped:(不可视,不可接受输入,不可执行代码)

其中(“Created”和“Started”)是瞬态,系统会通过调用下一个生命周期回调方法从这些状态快速移到下一个状态。 也就是说,在系统调用 onCreate() 之后,它会快速调用 onStart(),紧接着快速调用 onResume()。

1.2、从回调方法的角度,几种情况下的生命周期:

Paste_Image.png

1)activity第一次启动时,回调如下,对应图上的1:
onCreate()->onStart()->onResume()
2)此时用户打开另外一个新的Activity,或者切换到桌面,或者锁屏时,回调如下,对应图上的2:
onPause()->onStop()
3)这时再次回到原来的activity(重新点击原来Activity的图标,或者通过近期任务,或者解锁屏幕),回调如下对应图上的3:
onRestart()->onStart()->onResume()
4)这时候,如果按back键回退的时候,回调如下,对应图上的4:
onPause()->onStop()->onDestroy()
5)图上的5 是极端情况。用户很难重现这一情景的。
6)当Activity被系统回收后再次打开,生命周期跟情况1一样:
onCreate()->onStart()->onResume()

从整个生命周期来说: onCreate()和onDestory()是配对的,分别标识着activity的创建和销毁,并且只可能一次调用。
从activity是否可见来说: onStart()和onStop是配对的。
从Activity是否位于前台来说: onResume和onPause是配对的。

1.3、从一个activity启动另外一个activity时的情况:

新启动一个Activity时,旧的Activity的onPause方法先执行,再启动新的Activity:
例如从activityA通过startActivity启动activityB,回调如下:

activityA -> onPasuse() 
activityB -> onCreate() 
activityB -> onStart() 
activityB -> onResume() 
activityA-> onStop()

直接上一个测试图:
1)我再ActivityA中启动ActivityB,回调如下(每次启动新的Activity时候,都会调用onSaveInstanceState,后面会介绍):

Paste_Image.png

2)然后再按返回键,返回ActivityA,回调如下:

Paste_Image.png

2、异常情况下的生命周期

先来了解两个回调函数:
1)onSaveInstanceState函数
某些情况下,系统会自动调用它来保存Activity的一些数据,但当除它默认要保存的数据外,我们还要保存一些其他数据的时候, 我们就需要覆盖onSaveInstanceState()方法来保存Activity的附加信息。

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putInt("param", param);
    Log.i(TAG, "onSaveInstanceState called. put param: " + param);
    super.onSaveInstanceState(outState);
}

调用时机:当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。
这里的容易被销毁,指的是可能被系统销毁的时候(强调的是可能),主要有如下几种情况:

1、当用户按下HOME键时。
  这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,
  自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,
  让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则。
2、长按HOME键,选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从activity A中启动一个新的activity时。
5、屏幕方向切换时,例如从竖屏切换到横屏时。

2)onRestoreInstanceState函数
这个方法与onSaveInstanceState方法对应。在onSaveInstanceState中保存数据,那么则在onRestoreInstanceState中恢复数据。

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    param = savedInstanceState.getInt("param");
    Log.i(TAG, "onRestoreInstanceState called. get param: " + param);
    super.onRestoreInstanceState(savedInstanceState);
}

onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用。

异常情况主要有下面两种情况:

2.1、情况1:资源相关的系统配置发生改变

资源相关的系统配置发生改变,举个例子:当前Activity处于竖屏状态的时候突然转成横屏,系统配置发生了改变,Activity就会销毁并且重建。
测试代码:

public class LifeCycleActivity extends AppCompatActivity {
    private static final String TAG = "LifeCycleActivityTest";
    private Context context = this;
    private int param = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate called.");
        setContentView(R.layout.activity_life_cycle);
        Button btn_test = (Button) findViewById(R.id.btn_test);
        btn_test.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, TargetActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart called.");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart called.");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume called.");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause called.");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop called.");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestory called.");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putInt("param", param);
        Log.i(TAG, "onSaveInstanceState called. put param: " + param);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        param = savedInstanceState.getInt("param");
        Log.i(TAG, "onRestoreInstanceState called. get param: " + param);
        super.onRestoreInstanceState(savedInstanceState);
    }
}

1)启动Activity:

Paste_Image.png

2)直接按电源键锁屏:

Paste_Image.png

这时候调用了onSaveInstanceState方法。因为存在Activity被销毁的可能。
3)解锁屏幕:

Paste_Image.png

这时候并没有调用onRestoreInstanceState方法,因为Activity并没有被真正销毁重建。
4)然后我将手机屏幕从竖屏切换到横屏:

Paste_Image.png

这时候,onSaveInstanceState方法和onRestoreInstanceState方法都被调用了。因为Activity被系统重建了,而且是不为用户所知的情况下。
而且onSaveInstanceState必定是在onStop方法之前调用(与onPause方法的顺序不确定),onRestoreInstanceState必定是onStart方法后,onResume方法前调用。

2.2、情况2:资源内存不足导致低优先级Activity被杀死

Activity优先级

前台Activity——正在和用户交互的Activity,优先级最高
可见但非前台Activity——Activity中弹出的对话框导致Activity可见但无法交互
后台Activity——已经被暂停的Activity,优先级最低

系统内存不足时,会按照以上优先级杀死Activity,并通过onSaveInstanceState和onRestoreInstanceState这两个方法来存储和恢复数据。
这种情况是无法模拟的。但是函数调用情况跟情况1是一样的。

2.3 不让Activity重新创建的方法

系统配置有很多内容,当某项改变时,如果不想让Activity重新创建可以在AndroidMainfest中给Activity指定configChanges属性。

android:configChanges="xxx"
属性,常用的主要有下面三个选项:

 local:设备的本地位置发生了变化,一般指切换了系统语言;
 keyboardHidden:键盘的可访问性发生了变化,比如用户调出了键盘;
 orientation:屏幕方向发生了变化,比如旋转了手机屏幕。```
配置了android:configChanges="xxx"属性之后,Activity就不会在对应变化发生时重新创建,而是调用Activity的onConfigurationChanged方法。

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

推荐阅读更多精彩内容

  • 启动与销毁Activity 不同于使用 main() 方法启动应用的其他编程范例,Android 系统会通过调用对...
    安卓Boy阅读 1,749评论 3 5
  • 您的应用中的Activity应该做到如下需求: 1.用户在使用应用时接听来电或切换到另一个应用,它不会崩溃。 2....
    正阳Android阅读 522评论 1 0
  • 这是我第三遍看《Android开发艺术探索》这本书了,从第一遍看的云里雾里,第二遍略微明白之后,我决定看第三遍,并...
    陈添阅读 850评论 2 8
  • 高速路上的车海,火车站里的人山,轻叹一句回家即是一次炼狱。 经历30号和1号的人肉拼杀,在父母殷切期待下享受着美味...
    西贝南风2016阅读 291评论 3 2
  • 这些年一直在怀疑自己的文笔,胆怯让我没有勇气提笔。现在想想挺可笑的。人生如此短暂,...
    悦喜上眉梢阅读 142评论 0 0