美文网首页
重识Activity—Activity的生命周期

重识Activity—Activity的生命周期

作者: Android_程序媛 | 来源:发表于2019-04-19 19:37 被阅读0次

    继上篇重识Activity—Activity的基本使用文章之后,本次主要记录Activity的生命周期及简单实用。

    Activity的生命周期概念

    当用户浏览,退出和返回应用时,Activity实例会在其生命周期中转换为不同的状态。在生命周期回调方法中,可以声明用户离开并重新进入Activity时Activity的行为方式。每个回调允许执行适合于给定状态更改的特定工作。生命周期回调的良好实现可以帮助确保您的应用程序避免:

    • 如果用户在使用您的App时接到电话或切换到其他应用,则会崩溃;
    • 当用户不主动使用它时,消耗宝贵的系统资源;
    • 如果用户离开您的应用并稍后返回,则会丢失用户的进度;
    • 当屏幕在横向和纵向之间旋转时,会崩溃或丢失用户的进度。
    Activity的生命周期.png

    Activity生命周期主要有7个回调方法。其中,
    onCreate():创建Activity时回调执行的第一个方法,主要完成初始化操作,通过setContentView()加载布局,findViewById()绑定事件等,在整个生命周期中仅发生一次,是必须要重写的,而且第一行代码必须是调用父类的onCreate()方法,即:

    super.onCreate(savedInstanceState);
    

    该方法中传递一个Bundle对象,主要保存的是Activity不正常销毁时的状态。
    onStart():在Activity由不可见状态到可见状态时调用,表示Activity正在启动,主要工作是对资源加载。
    onResume():此时Activity处于可见状态并且可以和用户交互,位于Activity栈的栈顶,表示Activity可以进行编辑,捕获所有用户的输入。
    onPause():当Activity失去焦点,处于可见但不可编辑状态时调用,在这个方法中会将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。
    onStop():当Activity不再对用户可见时调用,仅在后台运行,在这个方法中可以进行释放资源等操作。
    onRestart():当处于“已停止”状态的Activity即将重新启动时调用。紧随其后调用onStart()
    onDestroy():当Activity被销毁时调用,通常实现释放资源、内存等操作。

    整个Activity的生命周期分为四个状态:

    • 运行状态(running):当前显示在屏幕的Activity,用户可见状态,可以与用户进行交互,执行:onCreate()----->onStart()----->onResume();
    • 暂停状态(paused):用户依旧可见,但是失去焦点,不可编辑,无法与用户进行交互,执行:onPause();
    • 停止状态(stopped):用户看不到当前界面,完全被覆盖,无法与用户进行交互,处于后台中运行,执行:onStop();
    • 销毁状态(killed):当前界面被销毁,等待被系统回收,执行:onDestroy()。

    注意:由于系统不足可能在暂停状态中直接被系统杀死会直接到销毁状态。

    下面,我通过在Activity中重写上述7种回调方法,在每个方法中通过Log日志,具体看一下Activity的生命周期:

    Activity的生命周期

    1. 启动MainActivity后:


      图1.png

    onCreate()--->onStart()--->onResume()

    1. 点击Home键:


      图2.png

    onPause()--->onStop()

    1. 再次进入MainActivity:


      图3.png

    onRestart()--->onStart()--->onResume()

    1. 按返回键,退出MainActivity:


      图4.png

    onPause()--->onStop()--->onDestroy()

    Activity横竖屏切换的生命周期

    准备工作:确保系统设置是否锁屏,如果锁屏,取消锁屏设置。

    1. 启动MainActivity:


      图5.png

    onCreate()--->onStart()--->onResume()

    1. 转换屏幕:


      图6.png

    onPause()--->onStop()--->onDestroy()
    --->onCreate()--->onStart()--->onResume()

    1. 再次转换屏幕:


      图7.png

    onPause()--->onStop()--->onDestroy()
    --->onCreate()--->onStart()--->onResume()

    1. 退出Activity:


      图8.png

    onPause()--->onStop()--->onDestroy()

    如果我们的需求是竖屏或者横屏时,我们需要给Activity设置属性android:screenOrientation,属性值为portrait(竖屏)或者landscape(横屏)。

    启动另一个Activity的生命周期

    以MainActivity(A)启动NormalActivity(B)为例:

    1. 启动A:


      图9.png

    A:onCreate()--->onStart()--->onResume()

    1. A启动B:


      图10.png

    A:onPause()
    B:onCreate()--->onStart()--->onResume()
    A:onStop()

    1. 按返回键退出B,显示A:


      图11.png

    B:onPause()
    A:onRestart()--->onStart()--->onResume()
    B:onStop()--->onDestroy()

    退出A同一个Activity退出是一样的,这里就不再描述。

    Activity启动Dialog样式的Activity的生命周期

    首先要确认我们创建的Activity是dialog样式的,例如,我创建了一个DialogActivity,继承Activity,在配置文件中设置它的样式:

    <activity
        android:name=".DialogActivity"
        android:theme="@android:style/Theme.Dialog">
    </activity>
    

    这个时候,我们定义MainActivity(A),NormalActivity(C),
    启动A,我就不再描述,直接看A启动C:


    图12.png

    A:onPause()
    C:onCreate()--->onStart()--->onResume()

    退出C,显示A:


    图13.png

    C:onPause()
    A:onResume()
    C:onStop()--->onDestroy()

    退出A不再描述。

    Activity启动Dialog或者PopupWindow的生命周期

    在MainActivity中定义两个按钮,一个是弹出Dialog,一个弹出PopupWindow。发现,弹出dialog或者PopupWindow后,生命周期没有任何的变化;取消dialog或者PopupWindow后也没有任何变化。

    总结:

    1. Dialog样式的Activity,虽然展示样式是Dialog,但是其本质是Activity;
    2. 弹出的Dialog,本质是Dialog;
    3. 弹出Dialog样式的Activity是会触发生命周期的回调方法的,但是Dialog和PopupWindow是不会触发生命周期的回调方法的。

    非典型生命周期的状态保存

    上述的生命周期图上,描述的是当Activity在暂停状态或者停止状态时,由于优先级较高的App内存不足,系统会将优先级较低的App销毁。这个时候,用户是不知道的,当用户再次打开发现原先的数据没有了,这样,就导致用户体验性不是很友好,所以,下面介绍两个方法:

    • onSaveInstanceState(Bundle outState):保存数据,Activity生命周期结束的时候,需要保存Activity状态的时候,会将要保存的数据以键值对的方式保存在Bundle对象中。

    调用时机:
    横竖屏切换时,会销毁当前Activity并重建;
    按下Home键、电源键:Activity进入了后台,其中按下电源键屏幕会熄灭;
    Activity被系统不正常销毁;
    启动其他Activity,Activity被压入了返回栈的栈底等。

    注意事项:
    用户主动销毁Activity时不会调用:当用户调用finish()方法或者用户按下返回键时;
    调用时机不确定:在onPause()之前或者之后,但是一定在onStop()之前;
    布局中组件状态存储:每个组件都实现了该方法,在调用的时候,会自动保存组件的状态,但是只有有id的组件才会保存;
    super.onSaveInstanceState(outState);该方法是默认实现组件保存状态的。

    • onRestoreInstanceState(Bundle savedInstanceState):Activity被不正常销毁再次恢复时被调用,通过Bundle对象中的键值对,获取保存的数据,组件的状态。Bundle对象也会传递到onCreate()方法中。如果系统没有销毁Activity,是不需要调用的。该方法会在onResume()方法之前回调。

    下面我以横竖屏切换为例,看一下上述两个方法的实现:
    我在Activity中实现这个回调方法,主要通过Log日志查看,具体代码:

        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            Log.d(TAG,"MainActivity***onSaveInstanceState");
            String tempData = "Something you just typed";
            outState.putString("data_key",tempData);
        }
    
        @Override
        protected void onRestoreInstanceState(Bundle savedInstanceState) {
            super.onRestoreInstanceState(savedInstanceState);
            Log.d(TAG,"MainActivity***onRestoreInstanceState():" + savedInstanceState.getString("data_key"));
        }
    

    上面已经描述了Activity的生命周期,这次作对比看一下有什么不一样的地方。
    启动MainActivity后查看Log日志:


    图14.png

    onCreate()--->onStart()--->onResume()

    我切换一下横竖屏:


    图15.png

    此时,发现Activity在执行完onPause()方法后执行了onSaveInstanceState(),然后又执行了onStop()--->onDestroy()--->onCreate()--->onStart()--->onRestoreInstanceState()--->onResume()。
    上面介绍onRestoreInstanceState()方法时已经说了Bundle对象也会传递到onCreate(Bundle savedInstanceState)中,下面是onCreate()方法中的部分代码:

    if(savedInstanceState != null){
        String tempData = savedInstanceState.getString("data_key");
        Log.d(TAG,"MainActivity***onCreate:" + tempData);
    }
    

    横竖屏切换后,通过Log日志查看:


    图16.png

    通过上图,可以看到我们保存的数据在onCreate中也能获取到,前提是Activity被不正常销毁,再次恢复数据。

    好了,以上就是我整理的关于Activity的生命周期的相关知识,如果有什么问题,大家可以积极留言,一起探讨!也请大家继续关注我的文章!

    相关文章

      网友评论

          本文标题:重识Activity—Activity的生命周期

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