知识点

在这里插入图片描述

一、 Activity的生命周期

onCreate:表示Activity正在被创建。生命周期的第一个方法,当打开一个activity时首先回调这个方法。在这个方法中一般做一些初始化工作,例如加载界面布局资源(setContentView)、数据初始化(findviewbyid)

onRestart : 表示Activity正在被重新启动。当前activity从不可见变为可见状态时这个方法就会回调。一般是用户行为导致,比如用户摁home键回到桌面,当用户再次回到本activity时,当前activity 走 onRestart->onStart->onResume

onStart :表示activity正在被启动。activity可见,未出现在前台。可以理解为activity已经显示出来了,但是我们看不到,不能与之交互。

onResume :表示activity已经可见,并且出现在前台,可以与用户进行交互。例如activity上有Button,此时我们就可以进行点击了。

onPause:表示activity正在停止,接着很快执行onStop。注意极端情况下,本Activity跳转其他activity后快速的回到当前activity时,当前activity的生命周期:onPause->onResume
但是这个“快速回到”要很快,一般情况下都是onPause->onStop->onRestart->onStart->onResume。这里不能做太耗时操作,可以做一些数据存储,动画停止工作。

onStop:表示activity即将停止,可以做一些回收工作。但是不能太耗时。

onDestroy :activity即将被销毁 ,activity生命周期最后一个回调,这里可以做一些回收工作,资源释放。

二、Activity生命周期图解

在这里插入图片描述

三、生命周期的切换过程实践

在面试Activity的基础时,两Activity切换时的生命周期执行顺序经常被考察,这里就以一个简单的🌰来实践下


public class MainActivity extends AppCompatActivity {

    public static final String TAG = "tags";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //打开Main2Activity
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, Main2Activity.class));
            }
        });
        Log.i(TAG, "onCreate:");
    }

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

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

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

    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop: ");
    }

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

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



public class Main2Activity extends AppCompatActivity {
    public static final String TAG = "tags";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2);
        Log.i(TAG, "Main2Activity onCreate:");
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "Main2Activity onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "Main2Activity onResume: ");
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "Main2Activity onPause: ");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "Main2Activity onStop: ");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "Main2Activity onRestart: ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "Main2Activity onDestroy: ");
    }
}

1、 启动MainActivity

在这里插入图片描述

MainActivity走 onCreate -> onStart -> onResume

2、由MainActivity跳转到Main2Activity

在这里插入图片描述

1、MainActivity 走 onPause
2、Main2Activity走 Main2Activity onCreate -> Main2Activity onStart -> Main2Activity onResume
3、MainActivity 走 onStop

注意

  • MainActivity与Main2Activity生命周期有交叉
  • 如果此时Main2Activity 已经设置了透明主题则mainActivity是不走onStop的,只走个onPause。从MainActivity跳转到Main2Activity 我们还是可以看见mainActivity,所以验证了onPause的可见不前台。
  • 展示对话框不影响生命周期。
3、在MainActivity页面摁Home键

在这里插入图片描述

MainActivity 走onPause -> onStop

4、摁Home后再次回到MainActivity时

在这里插入图片描述

此时MainActivity走了 onRestart -> onStart-> onResume

5、启动MainActivity 跳转到Main2Activity 再返回到 MainActivity

在这里插入图片描述

如上:
红圈1对应启动mainActivity
红圈2对应跳转到Main2Activity
红圈3对应再返回到 mainActivity

6、用户打开MainActivity然后摁back键

在这里插入图片描述

MainActivity走了 onPause->onStop->onDestroy

四、 生命周期小结

  • 整个生命周期来说onCreate和onDestroy 是配对的,分别代表着actiity的创建和销毁。并且只可能调用一次。
  • activity是否可见来说onStart和onStop是配对的,随着用户的操作两个生命周期可能被多次执行。
  • activity是否在前台来说onResume和onPause是配对的,随着用户的操作两个生命周期可能被多次执行。

五 、 问题思考

1、onStart 和 onResume ,onPause 和onStop从描述上差不多对我们来说有什么实质不同?

从使用过程来讲两对的确差不多,甚至我们可以只保留一对,比如只保留onStart 、onStop。根据上面的分析我们知道,这两对接口代表不同的意义:

onStart 、onStop是从是否可见的角度来回调的(前者可见后者不可见)。

onResume 、onPause,是从是否前台的角度来回调的(前者前台,后者非前台)

2、假设当前activity为A,如果这时用户打开新的activityB,B的onResume 和A的onPause那个先执行

执行结果 A:onPause->B:onCreate->B:onStart->B:onResume->A:onStop

六 、 异常情况下的生命周期

上述的摁Home键、摁返回键、摁按钮跳转页面都是正常情况下用户交互流程。其实Activity的生命周期还受如下因素影响,若如下条件触发时默认情况下Activity会销毁然后重建

  • 资源相关的系统配置发生改变:如横竖屏切换、系统语言切换等等。
  • 系统内存不足
1、资源相关配置发生改变导致Activity被杀死并重新创建🌰

在这里插入图片描述

默认情况下我们打开activity,activity走了 onCreate -> onStart -> onResume

在这里插入图片描述

在这里插入图片描述

进行屏幕旋转后我们发现activity走了 onPause -> onStop -> onDestroy -> onCreate -> onStart -onResume

可见资源相关配置发生改变,activity确实发生了销毁然后重建。

2、异常情况下数据的存储

activity在异常情况下会发生重建,那么页面上的数据我们如何恢复呢?activity提供两个回调方法用来进行异常情况下数据的存储、恢复。

(1)onSaveInstanceState(Bundle outState)

  • activity异常终止时系统会调用此方法来保存activity的状态,例如记录界面上输入框的文字、ListView滑动位置,重建时直接恢复这些状态
  • activity异常终止时我们也可以在这个方法中添加逻辑操作,存储我们想要的信息。
  • 注意这个方法在activity正常终止是不会回调的。

(2)onRestoreInstanceState(Bundle savedInstanceState)

  • 当activity异常终止重建时,系统会回调此方法,并把activity销毁时onSaveInstanceState方法所保存的Bundle 对象作为参数传递给onCreate和onRestoreInstanceState
  • 可通过onCreate和onRestoreInstanceState方法判断activity是否被重建。因为正常情况下Activity的onCreate方法的Bundle参数为null。异常情况下Bundle才非空。

下面举个🌰来验证Activity异常终止重建时

  • Activity会自动保存页面上UI的数据,并自动恢复。
  • 在activity异常终止时存储我们想要存储的信息,在activity重建时获取我们已经存储的信息
 @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.i(TAG, "onSaveInstanceState: ");
        //存下自定义数据
        outState.putString("tom","异常下存数据 :tom");
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.i(TAG, "onRestoreInstanceState: ");
        //读取存取的数据
        Log.i(TAG, " "+savedInstanceState.get("tom"));
    }

在这里插入图片描述

输入内容后点击按钮让屏幕旋转:
在这里插入图片描述
在这里插入图片描述
通过上述截图我们可以看到

  • EditText输入的文字在Activity销毁后重建得到恢复。
  • 我们自定义的数据在Activity销毁后重建得到恢复。

特别注意EditText控件一定要在xml布局中设置id,否则数据不会被恢复(原因参看EditText源码,内部有处理Activity如何帮view恢复数据的逻辑)

思考:onRestoreInstanceState和onCreate中都可以收到onSaveInstanceState存的Bundle值。这两个方法有啥区别?

  • onRestoreInstanceState
    只有异常声明周期下这个回调才会被调用(onSaveInstanceState也是)一旦被调用其参数savedInstanceState一定是有值的,我们不用额外判空。
  • onCreate
    如果是正常启动Activity时,onCreate方法的参数值为空,所以要使用参数值时要额外判空。
3、系统内存不足导致低优先级的activity被杀死

这种情况我们不好模拟,但是其生命周期、数据存储、的相关方法回调和资源配置发生改变回调是完全一致的。

系统内存不足时,系统总会优先杀死低进程的activity

Activity的优先级高低:

  • 前台activity:正在和用户交互的activity,优先级最高。

  • 可见但非前台activity:比如activity中弹出个对话框,导致activity还是可见,但是无法和用户交互了,优先级次于前台。

  • 后台activity:已经被停止的activity,比如执行了onstop。优先级最低。

安卓中的进程优先级从高到低:

前台进程 > 可见进程 > 服务进程 >后台进程 >空进程

七、避免资源配置改变导致Activity重新创建

资源配置改变可以不让activity重新创建吗?答案是有的:

1、在清单文件为activity指定configChanges = xxx,代表xxx模式下activity不会重新创建。

xxx有哪些值呢?可以参考下表

属性值含义
mccSIM卡唯一标识IMSI(国际移动用户识别码)中的国家代码,由三维数组组成,中国为460,此项标识mcc代码发生改变
mncSIM卡唯一标识IMSI(国际移动用户识别码)中的运营商代码,由两位数字组成,中国移动TD系统为00,中国联通为01中国电信为03,此项标识mnc代码发生改变
locale设备的本地位置发生改变,一般指切换了系统语言
touchscreen触摸屏发生了变化,这个可以忽略,正常情况下不会发生
keyboard键盘类型发生了变化 例如,用户插入了一个外置键盘。
keyboardHidden键盘的可访问性发生改变比如用户调出键盘
navigation系统导航方式发生改变,比如采用了轨迹球导航,很难发生,可以忽略
screenLayout屏幕布局发生改变,很可能用户激活了另外一个显示设备
fontScale系统字体缩放比例发生改变,比如用户选择了一个新字号
uiMode用户界面模式发生改变,比如是否开启了夜间模式(api 8新添加)
orientation屏幕方向发生改变,这个最常用,比如旋转了手机屏幕
screenSize当屏幕的尺寸信息发生改变,当旋转设备屏幕时,屏幕尺寸会发生改变,这个选项比较特殊,他和编译选项有关,当编译选项中的minSdkVersion和targetSdkVersion均低于13时此选项不会导致activity重启,否则导致activity重启(api 13新添加)
smallestScreenSize当设备的物理屏幕尺寸信息发生改变,这个属性值和屏幕的方向没关系,仅表示实际的物理屏幕发生改变时触发,比如用户切换到外设的显示设备,和screenSize一样,当编译选项中的minSdkVersion和targetSdkVersion均低于13时此选项不会导致activity重启,否则导致activity重启(api 13新添加)
layoutDirection当布局方向发生改变,这个属性用的比较少正常情况下无法修改布局的layoutDirection(api 17新添加)

configChanges的属性值如上表,配置多个属性值时使用|链接即可

2、重写activity的onConfigurationChanged方法

在activity发生xxx配置更改时onConfigurationChanged就会回调,这里我们可做一些监听工作。

小结

Activity的生命周期就详细的回顾了下~

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐