美文网首页Android知识
Activity生命周期解析、横竖屏切换引发问题和解决办法解析

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

作者: MLLWF | 来源:发表于2017-04-26 15:19 被阅读0次

前提

首先我们要知道,在系统中有一个专门用来管理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("此时为竖屏模式");
        }
    }

相关文章

网友评论

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

    本文链接:https://www.haomeiwen.com/subject/jxuizttx.html