android生命周期

简介

本文主要是对《Android 开发艺术探索》这本书关于Android生命周期的总结。

Activity的生命周期分为两部分内容,

  • 典型情况下的生命周期,所谓典型情况下的生命周期,是指在有用户参与的情况下,Activity所经过的生命周期的改变:
  • 异常情况下的生命周期。
    而异常情况下的生命周期是指Activity被系统回收或者由于当前设备的Configuration发生改变从而导致Activity被销毁重建,异常情况下的生命周期的关注点和典型情况下略有不同。

典型情况下的生命周期分析

在正常情况下,Activity会经历如下生命周期

  1. onCreate:
    表示Activity正在被创建,这是生命周期的第一个方法在这个方法中,我们可以做一些初始化工作,比如调用setContentView去加载界面布局资源、初始化Activity区所需数据等。

  2. onRestart:
    表示Activity正在重新启动。一般情况下,当当前Activity从不可见重新变为可见状态时,onRestart就会被调用。这种情形一般是用户行为所导致的,比如用户按Home键切换到桌面或者用户打开了一个新的Activity,这时当前的Activity就会暂停,也就是onPause和onStop被执行了,接着用户又回到了这个Activity,就会出现这种情况。

  3. onStart:表示Activity正在被启动,即将开始,这时Activity已经可见了(不是指肉眼可见),但是还没有出现在前台,还无法和用户交互。这个时候其实可以理解为Activity已经显示出来了,但是我们还看不到。

  4. onResume:
    示Activity已经可见了,并且出现在前台并开始活动。要注意这个和onStart的对比,onStart和onResume都表示Activity已经可见,但是onStart的时候Activity还在后台,onResume的时候Activity才显示到前台。

  5. onPause:
    表示Activity正在停止,正常情况下,紧接着onStop就会被调用。在特殊情况下,如果这个时候快速地再回到当前Activity,那么onResume会被调用。笔者的理解是,这种情况属于极端情况,用户操作很难重现这一场景。此时可以做一些存储数据、停止动画等工作,但是注意不能太耗时,因为这会影响到新Activity的显示,onPause必须先执行完,新Activity的onResume才会执行。

  6. onStop:
    表示Activity即将停止,可以做一些稍微重量级的回收工作,同样不能太耗时。

  7. onDestroy:
    表示Activity即将被销毁,这是Activity生命周期中的最后一个回调在这里,我们可以做一些回收工作和最终的资源释放

正常情况下,Activity的常用生命周期就只有上面7个,下图更详细地描述了Activity各种生命周期的切换过程。

在这里插入图片描述

针对图片,再附加一下具体说明:

(1)针对一个特定的Activity,第一次启动,回调如下:onCreate->onStart->onResume。

(2)当用户打开新的Activity或者切换到桌面的时候,回调如下: onPause->onStop。这里有一种特殊情况,如果新Activity采用了透明主题,那么当前Activity不会回调onStop。

(3)当用户再次回到原Activity时,回调如下: onRestart->onStart->onResumea

(4)当用户按back键回退时,回调如下:onPause->onStop->onDestroy (Android 12及以上 返回键不再调用onDestory方法,如果返回键想调用onDestroy方法,复写返回键的监听事件,执行finish方法,销毁activity)

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }

问题分析:

  • 假设当前 Activity 为 A,如果这时用户打开一个新 Activity B,那么 B 的 onResume和 A 的 onPause 哪个先执行呢?
    答案是A的onPause先执行,B的onResume后执行。(具体分析见android开发艺术探索)
    Android官方文档对onPause的解释有这么一句:不能在onPause 中做重量级的操作,因为必须onPause 执行完成以后新Activity才能Resume,从这一点也能间接证明我们的结论。通过分析这个问题,我们知道onPause和onStop都不能执行耗时的操作,尤其是onPause,这也意味着,我们应当尽量在onStop中做操作,从而使得新 Activity尽快显示出来并切换到前台。

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

我们知道,Activity 除了受用户操作所导致的正常的生命周期方法调度,还有一些异常情况,比如当资源相关的系统配置发生改变以及系统内存不足时,Activity 就可能被杀死。下面我们具体分析这两种情况:

1. 情况 1:资源相关的系统配置发生改变导致 Activity 被杀死并重新创建

理解这个问题,我们首先要对系统的资源加载机制有一定了解,这里不详细分析系统的资源加载机制,只是简单说明一下。拿最简单的图片来说,当我们把一张图片放在drawable目录后,就可以通过Resources去获取这张图片。同时为了兼容不同的设备,我们可能还需要在其他一些目录放置不同的图片,比如 drawable-mdpi、drawable-hdpi、drawable-land等。这样,当应用程序启动时,系统就会根据当前设备的情况去加载合适的Resources资源,比如说横屏手机和竖屏手机会拿到两张不同的图片(设定了landscape或者portrait状态下的图片)。比如说当前Activity处于竖屏状态,如果突然旋转屏幕 ,由于系统配置发生了改变,在默认情况下, Activity就会被销毁并且重新创建 ,当然我们也可以阻止系统重新创建我们的Activity.

在默认情况下,如果我们的 Activity 不做特殊处理,那么当系统配置发生改变后,Activity 就会被销毁并重新创建,其生命周期如下图所示

todo  添加图片

当系统配置发生改变后,Activity 会被销毁,其 onPause、onStop、onDestroy 均会被调用,同时由于Activity是在异常情况下终止的,系统会调用 onSaveInstanceState来保存当前Activity的状态。需要强调的一点是,这个方法只会出现在 Activity 被异常终止的情况下正常情况下系统不会回调这个方法。当Activity 被重新创建后,系统会调用 onRestoreInstanceState,并且把 Activity 销毁时onSaveInstanceState方法所保存的Bundle 对象作为参数同时传递给 onRestoreInstanceState和onCreate方法。因此,我们可以通过onRestoreInstanceState和onCreate方法来判断Activity是否被重建了,如果被重建了,那么我们就可以取出之前保存的数据并恢复,从时序上来说, onRestoreInstanceState的调用时机在onStart之后。

同时,我们要知道,在onSaveInstanceState和 onRestoreInstanceState方法中,系统自动为我们做了一定的恢复工作。当 Activity 在异常情况下需要重新创建时,系统会默认为我们保存当前 Activity 的视图结构,并且在 Activity 重启后为我们恢复这些数据,比如文本框中用户输入的数据、ListView滚动的位置等,这些 View 相关的状态系统都能够默认为我们恢复。具体针对某一个特定的View系统能为我们恢复哪些数据,我们可以查看View的源码。和Activity一样,每个View都有onSaveInstanceState和onRestoreInstanceState这两个方法,看一下它们的具体实现,就能知道系统能够自动为每个View恢复哪些数据。

onSaveInstanceState和 onRestoreInstanceState方法使用demo如下

public class MainActivity4 extends AppCompatActivity {

    private static final String TAG = "MainActivity4";

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


    @Override
    protected void onSaveInstanceState(@NonNull @NotNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("bundle_test","test");
        Log.d(TAG, "onSaveInstanceState: ");
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        String bundle_test = savedInstanceState.getString("bundle_test");
        Log.d(TAG, "onRestoreInstanceState: "+bundle_test);
    }


}

上面的代码很简单,首先我们在 onSaveInstanceState 中存储一个字符串,然后当 Activity被销毁并重新创建后,我们再去获取之前存储的字符串。接收的位置可以选择onRestoreInstanceState 或者 onCreate,二者的区别是:onRestoreInstanceState 一旦被调用,其参数Bundle savedInstanceState一定是有值的,我们不用额外地判断是否为空;但是onCreate 不行,onCreate 如果是正常启动的话,其参数 Bundle savedInstanceState 为 null.所以必须要额外判断。这两个方法我们选择任意一个都可以进行数据恢复,但是官方文档的建议是采用 onRestoreInstanceState 去恢复数据。

2. 情况2:资源内存不足导致低优先级的Activity被杀死

这种情况我们不好模拟,但是其数据存储和恢复过程和情况 1 完全一致。这里我们描述一下 Activity 的优先级情况。Activity 按照优先级从高到低,可以分为如下三种:

(1)前台 Activity——正在和用户交互的 Activity, 优先级最高。

(2)可见但非前台 Activity——比如 Activity 中弹出了一个对话框,导致 Activity 可见但是位于后台无法和用户直接交互。

(3)后台 Activity——已经被暂停的 Activity,比如执行了 onStop,优先级最低。

当系统内存不足时,系统就会按照上述优先级去杀死目标 Activity 所在的进程,并在后续通过onSaveInstanceState和onRestoreInstanceState来存储和恢复数数据。如果一个进程中没有四大组件在执行,那么这个进程将很快被系统杀死,因此,一些后台工作不适合脱离四大组件而独自运行在后台中,这样进程很容易被杀死。比较好的方法是将后台工作放入Service中从而保证进程有一定的优先级,这样就不会轻易地被系统杀死。

上面分析了系统的数据存储和恢复机制,我们知道,当系统配置发生改变后, Activity会被重新创建,那么有没有办法不重新创建呢?答案是有的,接下来我们就来分析这个问题。系统配置中有很多内容,如果当某项内容发生改变后,我们不想系统重新创建Activity,可以给 Activity 指定 configChanges 属性。比如不想让 Activity 在屏幕旋转的时候重新创建,就可以给 configChanges 属性添加 orientation这个值,如下所示。

android:configChanges="orientation|screenSize"

意思就是 你不想让哪个配置项影响重建Activity,就给Activity指定该configChanges属性。

该属性可以设置多个值,用“|”隔开,例如"orientation|screenSize" 设置了该属性之后,当指定的属性发生变化时,不会重新启动Activity,而是通知程序去调用Activity的onConfigurationChanged方法。

常见的属性内容如下:
todo 添加表

参考

《Android 开发艺术探索》

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值