Activity生命周期解析、横竖屏切换引发问题和解决办法解析

前提

首先我们要知道,在系统中有一个专门用来管理Activity实例对象的栈,这个堆栈采用的是“先进后出”的模式。我们每创建一个活动对象都会放进这个堆栈中,而最顶端的活动对象才是可见的并且可以和用户进行交互的!整个堆栈的活动过程如下图所示:

了解了堆栈之后,我们再看下官方最新的活动生命周期图:

其实我们平常在用APP的时候看到的APP界面就是以Activity(活动)为基础的,从而我们也能知道活动的最简单的功能就是可以给用户展示界面,并且和用户交互!从这个生命周期图中“visible”,“hidden”等字样我们也能看出这一现象!
那么我们在可以将活动的状态分为:

  • 创建(初始化)
  • 可见不可交互
  • 可见可交互
  • 部分可见不可交互
  • 不可见不可交互
  • 销毁

在结合上图,我们在分别说明一下图中的7个生命周期方法都有什么作用:

  1. onCreate() : 活动创建的时候被调用,创建之后之后活动被销毁了之后再次启动才会被调用。在这个方法中我们通常做一些初始化的工作,例如:控件的初始化,数据和控件的绑定等等!
     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    }
- 拓展说明:从上图中可以看到方法还带有一个Bundle类型的参数,Bundle类型大家应该知道它可以以键值对的形式存放许多类型的数据,所以这个参数可以用来恢复一些数据,至于是什么数据,并且这些数据是怎么来的,后面会详情说明的!
  1. onStart() :执行到这个方法的时候就是我们上面说的“可见不可交互”状态!

  2. onResume():执行到这个方法的时候就是我们上面说的“可见可交互”状态,这个时候活动是处于栈顶的!

  3. onPause():执行这个方法的时候,活动处于暂停状态,就是我们说的部分可见不可交互状态,比如:启动一个对话框模式的活动等,(特别注意:弹出的对话框并不能出发改方法)。从图中我们可以看到这个方法之后有两个路径,向前就是重新展示上一个活动,向后就是停止当前的活动!

  4. onStop():这个方法代表活动不再可见,也就是此时活动处于后台运行状态!这个可以有两个选择,要么就是通过onRestart()方法重新打开活动,要么就是执行onDestroy()销毁活动!

  5. onRestart():这个方法就是就是用来重新打开活动的,不知道这个方法有什么意义,官方给的解释就是:

    当您的Activity从停止状态返回前台时,它会接收对 onRestart() 的调用。系统还会在每次您的Activity变为可见时调用 onStart() 方法(无论是正重新开始还是初次创建)。 但是,只会在Activity从停止状态继续时调用 onRestart() 方法,因此您可以使用它执行只有在Activity之前停止但未销毁的情况下可能必须执行的特殊恢复工作。

  6. onDestroy():就是销毁活动的实例了,并且这个活动也将从活动栈的栈顶被清除!

梳理流程:

  1. 当我们启动活动的时候会执行: 此时活动可见可交互
  • onCreate()
  • onStart()
  • onResume()
  1. 之后的操作分两种情况:
  • 如果启动对话框模式的Activtiy或其他操作,使得当前活动部分不可见,则只会执行:

    • onPause()

      • 这种情况之后的操作也分两种:

        • onResume() 执行这个方法让活动重新处于前端
        • onStop() 执行这个方法让活动重新处于后台
  • 如果启动另一个活动,使得当前活动完全不可见了,则会执行:

    • onPause()

    • onStop()

      • 这种情况之后的操作也分两种:

        • onDestroy() 执行这个方法销毁活动
        • onRestart(),onStart(),onResume() 执行这些方法让重新打开活动

需要了解的在生命周期中的一些方法:

 @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        L.e("保存活动状态数据");
    }

这个方法是一定是在onStop()方法之前执行在但是不一定在onPause()之后执行,时序不能得到保证。该的方法可以通过Bundle类型的参数来保存活动的状态数据。这里保存的数据,可以在onCreate方法中的参数获取到!上面已经说过了!也可以通过下面的方法获取到:

 @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }

只要执行了这个方法就代表savedInstanceState参数里一定有数据,相反只有当savedInstanceState参数里有数据才会执行这个方法!但是onCreate方法却不一定,至于要在哪个方法里恢复数据,其实都可以!官方推荐是在onRestoreInstanceState这个方法中恢复数据;

上面这两个方法只会在活动异常终止的情况下执行,在正常通过返回键销毁活动的时候并没有执行该过程。

拓展知识:横竖屏切换

为什么会说这个呢,因为在手机进行横竖屏切换的时候,会引发活动生命周期的一轮变化,下面我通过打印的log进行说明:
首先看下代码:

QQ截图20170426150140.png

在剩下的生命周期方法中我也打印了相关日志,还有代码中的参数,之后我启动程序看打印的日志:

图片.png

执行了相关的周期方法,并且打印了参数值!这时候我手动旋转手机变成横向的再看打印的日志:

图片.png

从日志可以看出,先是执行了onPause(),onStop(),onDestroy(),把当前的活动销毁,之后又重新执行了一遍生命周期!

解决这个问题也很简单,就是在manifests文件生命这个活动的资源里添加这条属性:

图片.png

这两个值解释下:

orientation:屏幕方向发生变化,配置该参数可以解决横竖屏切换时,Activity重建问题(API<13)
screenSize:当设备旋转时,屏幕尺寸发生变化,API>13后必须配置该参数才可以保证横竖切换不会导致Activity重建。

这样切屏的时候就不再回调

 @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }

而是回调:

  @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        L.e("onConfigurationChanged");
    }

并且不会再引发生命周期的变化:

QQ截图20170426150630.png

** 并且可以通过一下方法来判断旋转之后的屏幕状态是横屏还是竖屏: **

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

推荐阅读更多精彩内容