Activity生命周期详细分析

本文将对Activity生命周期的分析分为两个部分:正常情况下的生命周期,异常情况下的生命周期,然后逐一将他们进行详细分析,看完这篇文章的读者应该对Activity生命周期有更深的了解

完整的Activity生命周期方法

onCreate

表示这个Activity正在被创建,这个方法我们肯定是最熟悉的了,因为我们通常在这个方法做一些初始化的操作,比如setContentView去加载布局文件初始化布局资源,一些界面所需要展示的数据也是放在这个方法进行加载。

onRestart

表示这个Activity重新启动,这个方法之后会重新调用onStart。

onStart

表示这个Activity已经启动了,但是还在后台,还不能跟用户进行交互,如果这个Activity要跟用户交互就会紧接着调用onResume,如果是进入后台就直接调用onStop。

onResume

表示这个Activity可见并且即将跟用户进行交互。

onPause

表示Activity正在停止,当我们按home键或者在这个Activity去启动另个Activity时会调用这个方法,一般情况下,这个方法调用之后会接着调用onStop方法,但是比如用户按home键之后又很快速的直接切换回这个Activity就有可能不触发onStop方法直接触发onResume方法,这个方法通常用于确认对持久性数据的未保存更改、停止动画以及其他可能消耗 CPU 的内容,但是这些内容不能太耗时。

onStop

表示这个Activity即将停止,我们可以在这个方法进行一些数据的回收工作,但是不能太耗时。

onDestroy

表示这个Activity即将被销毁,一般我们在这个方法对一些资源进行释放,比如动态监听一些系统广播的时候在这个方法去取消监听。


正常情况下Activity生命周期详细流程

下面这张图是直接从谷歌API指南拷过来的,说明了Activity生命周期可能的执行路径:



下面用代码打出相应的log分析回调的方法:

public class Activity13 extends Activity {
    private static String TAG = "print";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_btn);
        Log.d(TAG, "Activity13_onCreate");
    }

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

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

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

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

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "Activity13_onStop");

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Activity13_onDestroy");
    }
}
当启动这个Activity时,Log为:


可以看出当第一次启动一个Activity时回调顺序为:onCreate->onStart->onResume;


当按home键时,log为:


可以看出当切换到桌面时回调顺序为:onPause->onStop,但是有个特殊情况就是这个Activity使用了透明主题时,是不会回调onStop这个方法的。


然后我又重新切换回这个Activity,log为:


可以看到回调的方法为:onRestart->onStart->onResume;


当我按返回键时,log为:


可以看到回调的方法为:onPause->onStop->onDestroy;

然后我在原先的Activity上添加一个按钮,点击这个按钮跳转到另一个Activity,要启动的Activity名字为Activity14,Log为:


可以看到回调方法为:先调用栈顶Activity的onPause再调用要启动的Activity的onCreate->onStart->onResume方法,最后调用前一个Activity的onStop方法,这时候由于Activity的栈结构,原先的Activity并没有被销毁而是压在了新Activity下面。


这时当我按下返回键时,Log为:


可以看出这时是先回调Activity14的onPause方法,再回调Activity13的onRestart->onStart->onResume,再回调Activity14的onStop->onDestroy方法


所以分析得出,当从一个Activity跳转到另一个Activity时,首先回调的是前一个Activity的onPause才会回调要启动Activity的方法。


异常情况下Activity生命周期分析

(1).系统配置改变导致Activity被杀死并重新创建

这个场景我用了横竖屏这个例子来演示Activity的生命周期,当Activity正在交互时我把屏幕横屏了,这时log为:

可以看出,当我由竖屏转变为横屏时,系统会先调用onPause再调用onStop最后调用onDestroy销毁这个Activity,然后重新调用onCreate到onResume,这个方法照我们正常理解也能理解,比如我当我正常竖屏时图片这么大,但是我横屏了,屏幕宽度就变大了,这时在用这个图片就会很怪异了,所以Android系统在这时候就会重新加载布局资源(如果有)重新创建这个Activity,但是问题又来了,有些数据我们不想配置更改的时候被更改,Android系统能不能帮我们恢复呢,答案是肯定的,我做了个例子,如下图所示:



当我横屏时edittext保存了我的输入状态,既然当系统配置发生变化后Activity会被销毁,为什么还能保存这些状态呢,因为这种情况是属于异常状况,Android系统会调用onSaveInstanceState这个方法来保存Activity异常改变前的一些数据,这个数据被存储为一个Bundle对象,onCreate方法里的参数就是保存的信息,我们可以用代码来体现这个,代码如下:

public class Activity13 extends Activity {
    private static String TAG = "print";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_btn);
        Log.d(TAG, "Activity13_onCreate");
        if (savedInstanceState != null) {
            String saveBundle = savedInstanceState.getString("save_bundle");
            Log.d(TAG, "onCreate_save_bundle:"+ saveBundle);
        }
    }

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

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

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

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

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "Activity13_onStop");

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Activity13_onDestroy");
    }

    /**
     * 存储状态,只有异常销毁才会被调用,正常销毁不会调用
     *
     * @param outState
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("save_bundle", "outState");
        Log.d(TAG, "onSaveInstanceState");

    }

    /**
     * 恢复异常销毁时保存的状态
     *
     * @param savedInstanceState
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        String saveBundle = savedInstanceState.getString("save_bundle");
        Log.d(TAG, "onRestoreInstanceState:"+saveBundle);
    }
}


当我横屏时log为:


可以看出,当系统在异常终止的时候会在onPause方法之后调用onSaveInstanceState这个方法然后销毁这个Activity,当重新启动这个Activity时,系统会从onCreate参数中拿到销毁前保存的Bundle对象,然后在onResume前也从另一个方法去回复这些数据,正常情况下是不会触发这个过程的,既然onCreate里面已经有保存到销毁前的数据为什么Android系统还会专门做一个方法来恢复保存的数据?他们之间有什么区别?其实二者是有区别的,区别就是onCreate里的参数不一定有值,比如正常启动时就没值,但是onRestoreInstanceState这个方法一旦被触发,里面的参数Bundle saveInstanceState一定是有值得,不用额外判断是否为空,而在onCreate里面要进行非空判断,当然这两个方法可以选择任意一个进行数据恢复,他们的效果是一样的,官方建议是采用onRestoreInstanceState这个方法进行恢复。


顺便说明如果我们想横屏时不销毁Activity时有两种方法:

1:禁用横屏:在清单文件注册Activity时添加这个配置:

android:screenOrientation="portrait"
这样当我们横屏时Activity是不会改变的,相当于禁用了横屏

2:在清单文件注册Activity时添加这个配置:

android:configChanges="orientation|screenSize|keyboardHidden
这样横屏时销毁Activity不会重新走Activity的onCreate等一系列方法。

(2).系统资源不足导致优先级别低的Activity被杀死

Activity优先级从低到高有三种:调用了onStop方法的后台Activity,可见但不能交互的Activity(例如当前Activity弹出一个对话框),正在交互的前台Activity;

当系统内存不足时,会按照从低到高依次去杀死Activity,然后通过onStaveInstanceState和onRestoreInStanceState去存储和恢复数据。这时的生命周期跟前面分析的是一致的。

总结

Activity生命周期和横竖屏时的生命周期是面试常问的,懂得他们的生命周期能够在面试中加分,当然知道Activity的生命周期之后我们可以根据实际需要在相关的回调方法做一些操作,这样可以优化app的性能。


原创文章 17 获赞 14 访问量 3万+

猜你喜欢

转载自blog.csdn.net/lxzmmd/article/details/51338394