入栈的Activity由于系统资源不足被被回收了怎么办

本文探讨了Android应用中因内存不足导致活动被回收时如何通过onSaveInstanceState()方法保存临时数据,确保用户输入不会丢失。

 前面我们已经说过,当一个活动进入到了停止状态,是有可能被系统回收的。那么想象

以下场景,应用中有一个活动 A,用户在活动 A 的基础上启动了活动 B,活动 A 就进入了

停止状态,这个时候由于系统内存不足,将活动 A 回收掉了,然后用户按下 Back 键返回活

A, 会出现什么情况呢?其实还是会正常显示活动 A的, 只不过这时并不会执行 onRestart()

方法,而是会执行活动 A onCreate()方法,因为活动 A 在这种情况下会被重新创建一次。

这样看上去好像一切正常,可是别忽略了一个重要问题,活动 A 中是可能存在临时数据

和状态的。打个比方,MainActivity 中有一个文本输入框,现在你输入了一段文字,然后

启动 NormalActivity,这时 MainActivity 由于系统内存不足被回收掉,过了一会你又点击了

Back 键回到 MainActivity,你会发现刚刚输入的文字全部都没了,因为 MainActivity 被重新

创建了。

如果我们的应用出现了这种情况,是会严重影响用户体验的,所以必须要想想办法解决

这个问题。查阅文档可以看出,Activity 中还提供了一个 onSaveInstanceState()回调方法,这

个方法会保证一定在活动被回收之前调用,因此我们可以通过这个方法来解决活动被回收时

 临时数据得不到保存的问题。


 onSaveInstanceState()方法会携带一个 Bundle 类型的参数,Bundle 提供了一系列的方法

用于保存数据,比如可以使用 putString()方法保存字符串,使用 putInt()方法保存整型数据,

以此类推。每个保存方法需要传入两个参数,第一个参数是键,用于后面从 Bundle 中取值,

第二个参数是真正要保存的内容。

MainActivity 中添加如下代码就可以将临时数据进行保存:

@Override

protected void onSaveInstanceState(Bundle outState) {

super.onSaveInstanceState(outState);

  String tempData = "Something you just typed";

  outState.putString("data_key", tempData);

}

数据是已经保存下来了,那么我们应该在哪里进行恢复呢?细心的你也许早就发现,我

们一直使用的 onCreate()方法其实也有一个 Bundle 类型的参数。这个参数在一般情况下都是

null,但是当活动被系统回收之前有通过 onSaveInstanceState()方法来保存数据的话,这个参

数就会带有之前所保存的全部数据,我们只需要再通过相应的取值方法将数据取出即可。

修改 MainActivity onCreate()方法,如下所示:

 @Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Log.d(TAG, "onCreate");

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_main);

if (savedInstanceState != null) {

String tempData = savedInstanceState.getString("data_key");

Log.d(TAG, tempData);

}

……

}

取出值之后再做相应的恢复操作就可以了,比如说将文本内容重新赋值到文本输入框

上,这里我们只是简单地打印一下。

不知道你有没有察觉,使用 Bundle 来保存和取出数据是不是有些似曾相识呢?没错!

我们在使用 Intent 传递数据时也是用的类似的方法。这里跟你提醒一点,Intent 还可以结合

Bundle 一起用于传递数据的,首先可以把需要传递的数据都保存在 Bundle 对象中,然后再

Bundle 对象存放在 Intent 里。到了目标活动之后先从 Intent 中取出 Bundle,再从 Bundle

中一一取出数据。具体的代码我就不写了,要学会举一反三哦。


JVM 内存主要负责存储局部变量和方法调用信息,每个线程都有自己独立的,方法调用会创建,方法执行结束帧出。安卓 Activity 记录着 Activity和出操作,与 JVM 内存的操作逻辑类似。当 JVM 内存不足,会对安卓 Activity 产生多方面的影响: #### 无法创建新的 Activity 实例 创建新的 Activity 实例,需要在 JVM 中为其方法调用分配帧空间。如果内存不足,就无法为新的 Activity 方法调用分配足够的帧,导致 Activity 无法正常创建。例如在启动一个新的 Activity 系统调用一系列的方法,如 `onCreate()`、`onStart()` 等,这些方法的调用需要空间来存储局部变量和调用信息。当内存不足,就会抛出 `StackOverflowError` 异常,使得 Activity 无法启动。 #### Activity 方法调用异常 Activity 中的方法调用依赖于 JVM 内存。当内存不足,方法调用可能无法正常进行。例如,在 Activity调用一个递归方法或者嵌套层次较深的方法,由于空间不足,方法调用无法完成,可能会提前终止,导致 Activity 的功能无法正常实现。这种情况下,也会抛出 `StackOverflowError` 异常,影响 Activity 的正常运行。 #### 系统响应变慢甚至卡顿 JVM 内存不足会导致系统频繁进行垃圾回收或者尝试释放内存,这会占用大量的系统资源,使得系统响应变慢。在安卓应用中,Activity 的切换和交互会变得不流畅,用户点击按钮或者进行其他操作后,可能需要等待较长间才能得到响应,甚至出现卡顿现象。 #### 应用崩溃 如果 JVM 内存严重不足,无法满足 Activity 正常运行的基本需求,应用可能会直接崩溃。当系统无法为 Activity 的关键方法调用分配,会触发系统的异常处理机制,最终导致应用崩溃退出。 ### 示例代码 以下是一个简单的示例,模拟一个可能导致内存不足的情况: ```java public class MainActivity extends AppCompatActivity { private void recursiveMethod() { recursiveMethod(); // 递归调用,可能导致溢出 } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recursiveMethod(); } } ``` 在上述代码中,`recursiveMethod()` 方法不断递归调用自身,会不断在中创建新的帧,最终导致内存不足,抛出 `StackOverflowError` 异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值