Android应用开发—onSaveInstanceState方法什么时候被调用?

简介: 转载自onSaveInstanceState方法什么时候被调用?(转载/整理)在 Activity 被销毁之前被调用来保存每个实例的状态,这样就可以保证该状态能够从 onCreate(Bundle) 或者onRestoreInstanceState(Bundle)恢复过来。

转载自onSaveInstanceState方法什么时候被调用?(转载/整理)

  • 在 Activity 被销毁之前被调用来保存每个实例的状态,这样就可以保证该状态能够从 onCreate(Bundle) 或者onRestoreInstanceState(Bundle)恢复过来。 本方法在 Activity 可能被销毁前调用,这样当该 Activity 在将来某个时刻重新回来时可以恢复其之前的状态。例如,如果 Activity B 启用后位于 Activity A 的前端,在某个时刻 Activity A 因为系统回收资源的原因要被销毁,Activity A 有机会通过 onSaveInstanceState() 来保存其用户界面状态,使得将来用户返回到 Activity A 的时候能够通过 onCreate(Bundle) 或者onRestoreInstanceState(Bundle) 来恢复其界面状态。不要将这个方法和 Activity 生命周期中的回调如 onPause() 或 onStop() 搞混淆了,onPause() 在 Activtiy 被放置到后台或者自行销毁时总会被调用,onStop() 在 Activity 被销毁时被调用。一个会调用 onPause() 和 onStop() 但不会触发 onSaveInstanceState() 的例子是当用户从 Activity B 返回到 Activity A 时:没有必要调用 B 的 onSaveInstanceState(Bundle)方法,因为此时的 B 实例永远不会被恢复,因此系统会避免调用它。一个调用 onPause() 但不调用 onSaveInstanceState(Bundle) 方法的例子是当 Activity B 启动后处在 Activity A 的前端:如果在B的整个生命周期里 A 的用户界面状态都没有被破坏的话,系统是不会调用 Activity A 的onSaveInstanceState(Bundle)方法。默认的实现负责了大部分 UI 实例状态的保存,采用的方式是调用 UI 层上每个拥有 id 的 view 的 onSaveInstanceState()方法 ,并且保存当前获得焦点的 view 的 id (所有保存的状态信息都会在默认的 onRestoreInstanceState(Bundle) 实现中恢复)。如果你覆写这个方法来保存额外的没有被各个view保存的信息,你可能想要在默认实现过程中调用或者自己保存每个视图的所有状态。如果被调用,这个方法会在 onStop() 前被触发,但系统并不保证是否在 onPause() 之前或者之后触发。

  • Activity 中的 onSaveInstanceState() 方法和 onRestoreInstanceState() 方法并不是生命周期方法,它们不同于 onCreate()、onPause() 等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键),由系统销毁一个 Activity 时,onSaveInstanceState() 方法就会被调用。但是当用户主动去销毁一个 Activity 时,例如在应用中按返回键,onSaveInstanceState() 方法就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState() 方法只适合用于保存一些临时性的状态,而onPause() 方法适合用于数据的持久化保存。 另外,当屏幕的方向发生了改变, Activity 会被销毁并重新创建,如果你想在 Activity 被销毁前缓存一些数据,并且在 Activity 被重新创建后恢复缓存的数据。可以重写 Activity 中的 onSaveInstanceState() 方法和 onRestoreInstanceState()方法,如下:

    public class PreferencesActivity extends Activity {
      private String name;
      protected void onRestoreInstanceState(Bundle savedInstanceState) {
          // 重新创建后恢复缓存的数据
          name = savedInstanceState.getString("name");
          super.onRestoreInstanceState(savedInstanceState);
      }
      protected void onSaveInstanceState(Bundle outState) {
          // 被销毁前缓存一些数据
          outState.putString("name", "l_yqing");
          super.onSaveInstanceState(outState);
      }
    } 
  • 当用户启动一个新 Activity 之后,之前的 Activity 可能在内存中处于停止状态也可能由于新 Activity 需要更多内存而被系统销毁了,但不论怎样,当用户在新 Activity 上点击返回键时,他希望看到的是原先的 Activity 的界面。原先的 Activity 如果是被重新创建的,那么它就要恢复到用户最后看到它时的样子,我们该怎么做呢?其实也不难,在 onPause() 、onStop() 或 onDestroy() 中保存必要的数据就行了。但是现在Google又冒出一个新的东西:onSaveInstanceState(),观其名可知其意:它是专门用来保存实例状态的,这个“实例”不是指的 Activity 对象,而是它所在的进程,因为Activity 的销毁是因为它所在的进程被杀掉而造成的。onSaveInstanceState()是在系统感觉需要销毁Activity时调用的,它被传入一个参数Bundle,这个Bundle可以被认为是个 Map 字典之类的东西,用“键-值”的形式来保存数据。现在又叫人蛋疼了:不是可以在 onPause() 中保存数据吗?为什么又搞出这样一个家伙来?它们之间是什么关系呢? 原来,onSaveInstanceState() 方法的主要目的是保存和 Activity 的状态有关的数据,当系统在销毁 Activity 时,如果它希望 Activity 下次出现的样子跟之前完全一样,那么它就会调用onSaveInstanceState(),否则就不调用。所以要明白这一点:onSaveInstanceState() 方法并不是永远都会调用。比如,当用户在一个 Activity 点击返回键时,就不会调用,因为用户此时明确知道这个 Activity 是要被销毁的,并不期望下次它的样子跟现在一样(当然开发者可以使它保持临死时的表情,你非要这样做,系统也没办法),所以就不用调用onSaveInstanceState()。现在应该明白了:在onPause()、onStop() 以及 onDestroy() 中需要保存的是那些需要永久化的数据,而不是保存用于恢复状态的数据,状态数据有专门的方法:onSaveInstanceState()。数据保存在一个 Bundle 中,Bundle 被系统永久化。当再调用 Activity 的onCreate()时,原先保存的 Bundle就被传入,以恢复上一次临死时的模样,如果上次被销毁时没有保存 Bundle,则为 null。 还没完呢,如果你没有实现自己的 onSaveInstanceState(),但是 Activity 上控件的样子可能依然能被保存并恢复。原来 Activity 类已实现了onSaveInstanceState(),在 onSaveInstanceState() 的默认实现中,会调用所有控件的相关方法,把控件们的状态都保存下来,比如 EditText 中输入的文字、CheckBox 是否被选中等等。然而不是所有的控件都能被保存,这取决于你是否在 layout 文件中为控件赋了一个名字(android:id)。有名的就存,无名的不管。既然有现成的可用,那么我们到底还要不要自己实现 onSaveInstanceState() 方法呢?这就得看情况了,如果你自己的派生类中有变量影响到UI,或你程序的行为,当然就要把这个变量也保存了,那么就需要自己实现,否则就不需要,但大多数情况肯定需要自己实现一下下了。对了,别忘了在你的实现中调用父类的 onSaveInstanceState() 方法。
    注:由于 onSaveInstanceState() 方法并不是在每次被销毁时都会调用,所以不要在其中保存那些需要永久化的数据,执行保存那些数据的最好地方是在 onPause() 方法中。

转自heiguy的专栏onSaveInstanceState和onRestoreInstanceState触发的时机

先看Application Fundamentals上的一段话:

Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key) 从这句话可以知道,当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。 注意上面的双引号,何为“容易”?言下之意就是该activity还没有被销毁,而仅仅是一种可能性。这种可能性有哪些?通过重写一个activity的所有生命周期的onXXX方法,包括onSaveInstanceState和onRestoreInstanceState方法,我们可以清楚地知道当某个activity(假定为activity A)显示在当前task的最上层时,

其onSaveInstanceState方法会在什么时候被执行,有这么几种情况:

  • 当用户按下HOME键时。 这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则
  • 长按HOME键,选择运行其他的程序时。
  • 按下电源按键(关闭屏幕显示)时。
  • 从activity A中启动一个新的activity时。
  • 屏幕方向切换时,例如从竖屏切换到横屏时。

在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行 总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。

至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行

另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原。

目录
相关文章
|
1月前
|
Android开发 Swift iOS开发
iOS和安卓作为主流操作系统,开发者需了解两者差异以提高效率并确保优质用户体验。
【10月更文挑战第1天】随着移动互联网的发展,智能手机成为生活必需品,iOS和安卓作为主流操作系统,各有庞大的用户群。开发者需了解两者差异以提高效率并确保优质用户体验。iOS使用Swift或Objective-C开发,强调简洁直观的设计;安卓则采用Java或Kotlin,注重层次与动画。Swift和Kotlin均有现代编程特性。此外,iOS设备更易优化,而安卓需考虑更多兼容性问题。iOS应用仅能通过App Store发布,审核严格;安卓除Google Play外还可通过第三方市场发布,审核较宽松。开发者应根据需求选择合适平台,提供最佳应用体验。
58 3
|
1月前
|
Android开发 开发者
安卓应用开发中的自定义视图
【9月更文挑战第37天】在安卓开发的海洋中,自定义视图犹如一座座小岛,等待着勇敢的探索者去发现其独特之处。本文将带领你踏上这段旅程,从浅滩走向深海,逐步揭开自定义视图的神秘面纱。
37 3
|
1月前
|
存储 Android开发 开发者
深入理解安卓应用开发的核心组件
【10月更文挑战第8天】探索Android应用开发的精髓,本文带你了解安卓核心组件的奥秘,包括Activity、Service、BroadcastReceiver和ContentProvider。我们将通过代码示例,揭示这些组件如何协同工作,构建出功能强大且响应迅速的应用程序。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和深度知识。
|
1月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
72 0
|
19天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
43 15
Android 系统缓存扫描与清理方法分析
|
1天前
|
Android开发 Swift iOS开发
深入探索iOS与Android操作系统的架构差异及其对应用开发的影响
在当今数字化时代,移动设备已经成为我们日常生活和工作不可或缺的一部分。其中,iOS和Android作为全球最流行的两大移动操作系统,各自拥有独特的系统架构和设计理念。本文将深入探讨iOS与Android的系统架构差异,并分析这些差异如何影响应用开发者的开发策略和用户体验设计。通过对两者的比较,我们可以更好地理解它们各自的优势和局限性,从而为开发者提供有价值的见解,帮助他们在这两个平台上开发出更高效、更符合用户需求的应用。
|
10天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
10天前
|
Android开发 Swift iOS开发
探索iOS与安卓应用开发的差异性
探索iOS与安卓应用开发的差异性
28 2
|
17天前
|
传感器 XML IDE
探索安卓应用开发:从基础到进阶
【10月更文挑战第23天】在数字化时代的浪潮中,移动应用已成为人们日常生活的延伸。本文以安卓平台为例,深入浅出地介绍了如何从零开始构建一个安卓应用,涵盖了开发环境搭建、基本组件使用、界面设计原则以及进阶技巧等关键步骤。通过实例演示和代码片段,引导读者逐步掌握安卓应用开发的核心技能,旨在激发更多开发者对安卓平台的探索热情,并为初学者提供一条清晰的学习路径。
|
5天前
|
前端开发 Android开发 UED
安卓应用开发中的自定义控件实践
【10月更文挑战第35天】在移动应用开发中,自定义控件是提升用户体验、增强界面表现力的重要手段。本文将通过一个安卓自定义控件的创建过程,展示如何从零开始构建一个具有交互功能的自定义视图。我们将探索关键概念和步骤,包括继承View类、处理测量与布局、绘制以及事件处理。最终,我们将实现一个简单的圆形进度条,并分析其性能优化。