美文网首页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