Android---Activity 生命周期(四)Recreating Activity

本文深入探讨了Android应用中Activity被销毁的原因及其影响,并详细解释了如何通过重写onSaveInstanceState()和onRestoreInstanceState()方法来保存和恢复Activity的状态数据,确保用户体验连续性和数据完整性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1》There are a few scenarios in which your activity is destroyed due to normal app behavior, such as when the user presses the Back button or your activity signals its own destruction by calling finish(). The system may also destroy your activity if it's currently stopped and hasn't been used in a long time or the foreground activity requires more resources so the system must shut down background processes to recover memory.

<翻译>Activity被销毁的一些情况:

(1)用户点击了“返回键”;

(2)Activity自身调用finish()方法来触发自身的销毁;

(3)当Activity当前处于Stopped状态时且很久没有被使用了,系统也会销毁该Activity。或者是前台Activity需要更多的资源时,这时系统必须销毁后台进程以便获得内存,供前台Activity运行使用。


 2》When your activity is destroyed because the user presses Back or the activity finishes itself, the system's concept of that Activity instance is gone forever because the behavior indicates the activity is no longer needed. 

<翻译>当你的Activity因为用户点击返回键或者是Activity自身结束自己导致的销毁时,系统都会认为该Activity的实例会永远消失,因为以上行为表明该Activity不再需要了。


However, if the system destroys the activity due to system constraints (rather than normal app behavior), then although the actual Activity instance is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed. 

The saved data that the system uses to restore the previous state is called the "instance state" and is a collection of key-value pairs stored in a Bundle object.

<翻译>然而,如果是因为系统限制(而不是正常的app操作行为)导致的Activity销毁,那么,尽管实际上该Activity实例已经被销毁了,系统会记得它存在过,这样当用户再次回到该Activity时,系统会使用一组描述该Activity被销毁时的状态值再重新创建一个该Activity的实例。

那些被系统用来恢复销毁前状态的保存数据称为"实例状态"("instanse state"),是保存在Bundle对象中的一组key-value对。


3》By default, the system uses the Bundle instance state to save information about each View object in your activity layout (such as the text value entered into an EditText object). So, if your activity instance is destroyed and recreated, the state of the layout is restored to its previous state with no code required by you. However, your activity might have more state information that you'd like to restore, such as member variables that track the user's progress in the activity.

<翻译>默认情况下,系统会使用Bundle实例状态来保存Activity布局中每一个View对象的状态(如用户在EditText输入的信息)。所以,当你的Activity实例被销毁后再被重新创建时,你不必编写任何代码就可以将layout恢复到销毁前的状态。但是,你的Activity可能有更多你想恢复的数据要恢复,如activity中用来记录用户进度的成员变量。


Note: In order for the Android system to restore the state of the views in your activity, each view must have a unique ID, supplied by the android:id attribute.


4》

To save additional data about the activity state, you must override the onSaveInstanceState() callback method. The system calls this method when the user is leaving your activity and passes it the Bundle object that will be saved in the event that your activity is destroyed unexpectedly. If the system must recreate the activity instance later, it passes the same Bundle object to both the onRestoreInstanceState() and onCreate() methods.

<翻译>为了保存其他的跟Activity有关的数据,必须要重写onSaveInstanceState()回调方法。当用户正要离开该Activity时,系统会调用该方法(onSaveInstanceState方法),并传递该方法一个Bundle 对象,该Bundle对象将会被保存在Activity中意外被销毁的事件中。如果以后系统一定要重新创建该Activity的话,系统会同时给onRestoreInstanceState()方法和onCreate()方法传递上面提到的那个Bundle对象。



Figure 2. As the system begins to stop your activity, it calls onSaveInstanceState() (1) so you can specify additional state data you'd like to save in case the Activity instance must be recreated. If the activity is destroyed and the same instance must be recreated, the system passes the state data defined at (1) to both the onCreate() method (2) and the onRestoreInstanceState() method (3).
<翻译>图2. 当系统开始停止你的Activity时,系统会调用onSaveInstanceState() 方法(1),这样你就可以指定其他的你想保存的状态数据,以防该Activity实例必须要被重创建时使用。如果该Activity实例被销毁后又必须要被重新创建时,系统会把在(1)定义的状态数据传递给onCreate()方法(2)和onRestoreInstanceState()方法(3)。


5》Save Your Activity State----保存Activity的状态数据

As your activity begins to stop, the system calls onSaveInstanceState() so your activity can save state information with a collection of key-value pairs. 

The default implementation of this method saves information about the state of the activity's view hierarchy, such as the text in an EditText widget or the scroll position of a ListView.
<翻译>onSaveInstanceState()方法的默认实现是保存Activity中的View的状态,如EditText中的输入的数据或者是ListView的滑动的位置。


To save additional state information for your activity, you must implement onSaveInstanceState() and add key-value pairs to the Bundle object.

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);
}


6》Restore Your Activity State----恢复Activity的状态信息

When your activity is recreated after it was previously destroyed, you can recover your saved state from the Bundle that the system passes your activity. Both the onCreate() and onRestoreInstanceState() callback methods receive the same Bundle that contains the instance state information.

Because the onCreate() method is called whether the system is creating a new instance of your activity or recreating a previous one, you must check whether the state Bundle is null before you attempt to read it. If it is null, then the system is creating a new instance of the activity, instead of restoring a previous one that was destroyed.

<翻译>因为,不论是创建一个新的Activity实例还是重新创建一个之前销毁的Activity实例,系统都调用onCreate()方法,所以在你尝试读取状态数据之前一定要检查一下状态Bundle是否为空。如果为空,那么系统是要创建一个新的Activity实例而不是恢复之前被销毁的Activity实例。


For example, here's how you can restore some state data in 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
    }
    ...
}

Instead of restoring the state during onCreate() you may choose to implement onRestoreInstanceState(), which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null:

<翻译>相比在onCreate()方法中恢复状态数据,你可能会选择在onRestoreInstanceState()方法中恢复,系统会在调用过onStart()方法后调用它(onRestoreInstanceState方法)。系统只有在有一个保存状态可以要恢复时才会调用onRestoreInstanceState()方法,所以你不必再检查Bundle对象是否为空了:


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);
}
### Locale-Emulator 报错解决方案 在使用 Locale-Emulator 时,可能会遇到各种错误情况。以下是常见的错误及其对应的解决方案: #### 1. **无法模拟区域设置** 如果发现 Locale-Emulator 未能成功更改设备的语言或地区设置,可能是由于权限不足或其他配置问题引起的。可以通过以下方式解决: - 确保已授予应用所需的权限,例如 `WRITE_SETTINGS` 或者 `SYSTEM_ALERT_WINDOW` 权限[^1]。 - 如果是在 Android 10 及以上版本运行,可能需要额外启用开发者选项中的“允许调试 APK”功能。 #### 2. **ADB 命令执行失败** 当尝试通过 ADB 控制 Locale-Emulator 的行为时,可能出现命令执行失败的情况。例如,在停止 QQ 应用的过程中出现问题: ```bash [D:\android-sdk-windows\platform-tools\adb.exe -P 5037 -s emulator-5554 shell am force-stop com.tencent.mobileqqi] ``` 这通常是因为目标设备未连接、包名拼写错误或者服务不可用所致[^2]。可以按照以下步骤排查: - 验证设备是否正常连接并处于可调试状态:`adb devices`。 - 检查指定的应用包名是否正确。 - 尝试重启 ADB 服务器:`adb kill-server && adb start-server`。 #### 3. **窗口管理异常** 某些情况下,Locale-Emulator 可能会抛出类似于以下的错误: ```plaintext android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application ``` 这种问题是由于窗口令牌无效造成的。具体原因和修复方法如下: - 错误通常是由于上下文不匹配引起,比如使用了 `getApplicationContext()` 而非 Activity 上下文[^3]。 - 修改代码逻辑,将 `getApplication()` 替换为当前 Activity 实例(即 `this`),从而确保正确的上下文传递。 #### 4. **广播接收器注册问题** 如果 Locale-Emulator 使用了动态广播接收器,则可能存在未注销广播接收器的风险。典型表现为日志中提示类似以下内容: ```plaintext call you are unregister onbrocastRevicer? ``` 这是由于忘记调用 `unregisterReceiver()` 方法导致的资源泄漏问题[^3]。建议在生命周期结束前显式注销广播接收器。 #### 5. **更新冲突** 安装过程中出现以下错误信息: ```plaintext INSTALLATION error: INSTALL_FAILED_UPDATE_INCOMPATIBLE ``` 该问题表明旧版应用尚未完全卸载就试图覆盖安装新版本[^3]。推荐的操作流程包括: - 手动删除现有应用实例后再重新部署。 - 清理缓存数据以及关联文件夹路径下的残留记录。 #### 6. **R.java 文件丢失** 开发阶段偶尔会发生 R.java 自动移除的现象,并伴随重建需求的通知: ```plaintext R.java was removed! Recreating R.java! ``` 此类警告一般不会影响最终产物质量,但仍需注意保持构建环境稳定性和依赖同步准确性[^3]。 --- ### 示例代码片段 下面提供一段简单的脚本用于验证 Locale-Emulator 是否能够切换至特定语言环境: ```java import android.content.Context; import android.os.LocaleList; public class LocaleHelper { public static void setAppLocale(Context context, String languageCode) { LocaleList localeList = new LocaleList(new Locale(languageCode)); LocaleList.setDefault(localeList); Configuration config = context.getResources().getConfiguration(); config.setLocales(localeList); context.createConfigurationContext(config); // Apply changes immediately. } } ``` --- ### 总结 针对 Locale-Emulator 中常见的一些报错现象进行了分析说明,并给出了相应的调整措施。实际操作时还需结合具体情况灵活应对。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值