Activity销毁与重建

翻译自官方文档:Receating an Activity

更透彻的关于onSaveInstanceState()函数保存数据,onRestoreInstanceState()函数和onCreate()函数恢复数据的整个流程及源代码理解请参考博文:深入理解onSaveInstanceState & onRestoreInstanceState 方法

点击打开链接


Activity在以下几种情况下由于正常的应用操作会被销毁,例如:当用户按下后退键或者是Activity本身调用了finish()方法。此外,如果你的Activity生命周期处于stop状态而且一段时间内都没有被调用或者是处于前台的Activity需要更多的资源而系统资源紧张的时候,系统也会销毁你的Activity,杀掉后台进程给前台进程留出足够的内存。


当你的Activity由于用户按下后退键或者是Activity本身调用了finish()方法时,系统认为该Activity将会永远消失,因为前面两种情况表明该Activity不再被需要。然而,如果系统由于本身的限制不得不销毁Activity而不是应用本身的行为销毁Activity,尽管该Activity已经消失,但是系统仍然记得它。只要用户重新进入该Activity,系统就会利用系统自己销毁该Activity时保存的一些描述该Activity状态的数据来重新创建一个新的Activity。这些系统用于恢复之前Activity状态而保存的数据叫做“实例状态”,它本质上是一些键值对,并保存在Bundle对象中。


警告:当用户进行横竖屏切换的时候,你的应用的当前Activity机会被销毁和重建。当屏幕更改方向时,由于屏幕的改变,当前Activity需要重新加载交互资源,必须布局资源,此时系统就会销毁和重建前台Acitvity。


默认情况下,系统使用Bundle实例状态来保存你的Activity中的View对象的信息,比如 EditText 可编辑框中输入的数据。所以,如果你的Activity被销毁和重建,你的布局资源的状态会保存当前被销毁的Activity的状态,而这些并不用你自己编写代码实现。然而,你自己本身可能会有想要保存的数据,比如当前要被销毁的Activity中的一些变量的值。


注解:为了android熊够恢复你的Activity的一些View的状态,每一个要保存的View必须包含唯一的ID,这个ID 就是我们在xml文件中定义是所写的 android:id  这个属性。



为了保存一些这个被销毁的Acitvity的额外数据,你必须复写 onSaveInstanceState() 回调函数。当用户将要离开这个Activity的时候,系统就会调用这个回调函数,并且传递 给它一个Bundle对象作为参数,当你的activity被突然销毁时,这个Bundle对象就会保存该Activity的一些状态值,其他情况下该Bundle的值均为null。如果系统之后必须恢复activity实例,它就会传递刚刚保存被销毁的Activity的实例状态这个Bundle对象给onRestoreInstanceState()方法和onCreate()方法。


如上图:当系统要停止你的Activity的时候,系统会调用onSaveInstanceState()方法,所以你可以添加你想保存的额外状态数据以防止Activity被销毁重建。如果activity被销毁而且要重建一个相同的activity实例,系统就会传递之前保存的状态数据(保存在Bundle中)给onCreate()方法和onRestoreInstanceState()方法。


保存Activity状态

当你的Activity要开始进入stop生命周期的时候,系统会调用onSaveInstanceState()方法,所以你的activity能够保存一些状态信息到键值对中。该函数的默认实现保存的信息是该Activity的层次视图(view hierarchy),比如EditText控件中的内容,或者是ListView中的滚动的位置。

为了在Activity中保存额外的状态信息,你必须实现onSaveInstanceState()方法,并添加键值对到Bundle对象中,如下:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

警告:复写该方法时要调用onSaveInstanceState()方法的父类实现,默认的实现方法才会保存该Activity的阶级视图。

恢复Activity数据

当你的Activity之前被销毁后要重建时,你可以从之前保存的Bundle对象中恢复数据。onCreate()和onRestoreInstanceState()两个回调函数都会接收到相同的,包含之前保存的状态信息的Bundle对象。

由于onCreate()方法不管是新建一个新的Activity实例或者是重建一个Activity实例都会被调用,所以在你要读取Bundle这个对象之前你必须检测一下Bundle对象是否为null,如果是null,系统就新建一个新的Activity实例,如果不是null,则重建一个Activity实例。

下面这个例子展示了如何在onCreate()方法中恢复数据:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first
   
    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

你应该选择复写实现onRestoreInstanceState()方法,这个方法是在onStart()方法之后被调用的,而不是选择实现onCreate()方法去恢复数据。系统只有当保存了状态数据要恢复的时候才会调用onRestoreInstanceState()方法,所以我们不需要检测它的参数Bundle对象是否为null。一个实例如下:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);
   
    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

警告:复写该方法时要调用该方法的父类实现,默认的实现方法才会保存该Activity的阶级视图。




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值