Activity 异常生命周期

Activity 异常生命周期

说道Activity的生命周期相信所有Android开发者都耳熟能详,但那些只是一般情况下,除此以外Activity还存在异常情况的生命周期。

造成异常情况的发生主要分为以下两种:1、用户操作导致。2、系统自愿发生改变及内存不足。

Activity状态和内存的关系

系统会在需要释放内存的时候杀死进程,一个进程是否会被系统杀死取决于当时的状态,而进程的状态往往取决于其Activity的状态。以下是几种常见的状态和其对应的情况:

Likelihood of being killedProcess stateActivity state
LeastForeground (having or about to get focus)Created Started Resumed
MoreBackground (lost focus)Paused
MostBackground (not visible)Stopped
MostEmptyDestroyed

可以看出,当Activity处于后台时其进程都是有可能被杀掉的。

Activity和系统配置

理解这个问题,首先要对系统的资源加载机制有一定了解,举个栗子,Activity中加载图片,通常会将图片保存在项目drawable目录中通过resources进行获取,Android为了兼容不同版本所有资源文件都有资源限定符的概念,不清楚的可以看Android资源限定符。这样,当应用启动时就会根据当前设备的情况去加载合适的Resource资源了。

比如,横竖屏可能会拿到两张不同的图片,因此,当Activity在运行中突然发生屏幕旋转情况时,由于系统配置发生了改变,默认情况Activity就会被销毁,当然也可以通过配置阻止销毁,这是后话了。

Activity的异常重建

异常重建的主要方式

上面说到了Activity发生异常销毁的两种可能,那为什么有时即便被销毁了我们依然可以重新看到界面呢,这就是Android的异常重建机制了。

为了保证用户体验,当Activity是在异常情况下终止时系统会调用采用状态保存和回复两套流程来恢复之前的状态。

  • onSaveInstanceState保存状态,该方法在onStop之前,无论是否发生异常均会调用该方法。
  • onRestoreInstanceState恢复状态,该方法在onStart之后,仅发生异常时调用。除此之外,我们熟悉的onCreate(savedInstanceState: Bundle?)也有类似的功能,其中参数savedInstanceState就是保存的状态。

不同版本调用逻辑略有不同:

private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {
        // Before P onSaveInstanceState was called before onStop, starting with P it's
        // called after. Before Honeycomb state was always saved before onPause.
        final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null
                && !r.isPreHoneycomb();
        final boolean isPreP = r.isPreP();
        if (shouldSaveState && isPreP) {
            callActivityOnSaveInstanceState(r);
        }
        
        try {
        	// 执行Activity onStop
            r.activity.performStop(r.mPreserveWindow, reason);
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException(
                        "Unable to stop activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
            }
        }
        r.setState(ON_STOP);
        // .....
        if (shouldSaveState && !isPreP) {
            callActivityOnSaveInstanceState(r);
        }
    }

    private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
            PendingTransactionActions pendingActions) {

        // Pre-Honeycomb apps always save their state before pausing
        final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
        if (shouldSaveState) {
            callActivityOnSaveInstanceState(r);
        }
		
		// 执行Activity onPause
        performPauseActivityIfNeeded(r, reason);

HONEYCOMB 11 之前 onPause 前调用
P 28之前 onStop 前调用
P 28及之后 onStop 后调用

异常重新的具体流程

通过onSavedInstanceStateonRestoreInstanceState,系统自动为我们做了一定的恢复工作,例如文本框的数据,ListView滚动位置等等。那这些具体是如何实现的呢?

首先是Activity被意外终止,调用onSave..去保存数据,然后Activity会委托Window,Window再委托其上的顶级容器,通常顶级容器就是我们知道的DecorView。最后由DecorView遍历自身子元素去一一保存数据。因此特定View的数据保存和恢复其实是View自身实现的。查看顶级View的源码,发现一样具备onSave..onRestore..两个方法,也就是说如果我们需要对某个View的异常状态进行保存,只需要重写onSave..onRestore..两个方法就可以了。

重建范例

View的重建主要是通过两个主方法中savedInstanceState: Bundle?参数完成的。以下是官方文档中举得例子:

companion object {
    val STATE_SCORE = "playerScore"
    val STATE_LEVEL = "playerLevel"
}

override fun onSaveInstanceState(outState: Bundle?) {
    // Save the user's current game state
    outState?.run {
        putInt(STATE_SCORE, currentScore)
        putInt(STATE_LEVEL, currentLevel)
    }

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(outState)
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState) // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        with(savedInstanceState) {
            // Restore value of members from saved state
            currentScore = getInt(STATE_SCORE)
            currentLevel = getInt(STATE_LEVEL)
        }
    } else {
        // Probably initialize members with default values for a new instance
    }
    // ...
}

override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState)

    // Restore state members from saved instance
    savedInstanceState?.run {
        currentScore = getInt(STATE_SCORE)
        currentLevel = getInt(STATE_LEVEL)
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值