Saving UI States(保存UI状态)

您做或不做UI方式是用户体验的重要组成部分。无论用户是否旋转设备,用户重新启动应用程序,还是系统关闭应用程序,重要的是您的活动保持用户期望的状态。

在要保存的UI数据简单轻量的情况下,您可以onSaveInstanceState()单独使用 来保存您的状态数据。在您想要保留复杂数据的情况下,可以使用 ViewModel对象, onSaveInstanceState()方法和持久本地存储的组合。

本页讨论了每种方法。

处理更简单的情况:onSaveInstanceState()


onSaveInstanceState() 如果系统停止并稍后重新创建该控制器,则该回调旨在存储相对少量的数据,以轻松地重新加载UI控制器的状态,如活动或片段。此回调旨在处理两种情况:

  • 由于内存限制,系统 在应用程序处于后台时会杀死应用程序的进程。
  • 出现 配置更改,例如屏幕旋转或更改为输入语言。

正如这两种情况所暗示的, onSaveInstanceState()在系统停止活动但未完成活动的情况下被调用。例如,如果用户离开应用几个小时,并且系统从内存中弹出相关进程,则系统会调用缺省实现 onSaveInstanceState() 来保存每个具有ID的UI控制器。稍后,当用户返回到应用程序时,系统会 从保存的状态恢复活动。

注意: onSaveInstanceState()当用户明确关闭活动或在其他情况下finish()调用时 不会调用。

系统会自动为您保存和恢复大量UI数据:默认实现 onSaveInstanceState()保存有关活动视图层次结构状态的信息,例如EditText小部件中的文本或小部件的滚动位置 ListView。您也可以通过重写onSaveInstanceState()回调来将自定义数据保存到此捆绑包中 。如果您重写此方法以保存未由每个实体捕获的附加信息,则应调用默认实现,除非您准备自行保存每个实体的状态。

onSaveInstanceState()不适用于存储大量数据(如位图)或需要冗长序列化或反序列化的复杂数据结构。如果序列化的对象很复杂,则序列化会消耗大量内存。由于此过程在配置更改期间发生在主线程上,因此序列化可能会导致丢帧和视觉延迟(如果时间过长)。因此,不要使用onSaveInstanceState() 复杂的数据结构,确保将这些结构存储在本地持久性存储中; 创建数据后尽快存储这些数据是一个好主意,以尽量减少丢失数据的可能性。然后,使用 onSaveInstanceState()为每个这些对象存储唯一的ID。

本文档的下一部分提供了有关保留更复杂数据的更多详细信息。

管理更复杂的状态:分而治之


如果在活动结束时需要保留更复杂的数据结构,则可以通过将工作分为几种类型的存储机制来有效地保存和恢复UI状态。

用户可以通过两种常规方式离开一项活动,从而导致用户期望得到两种不同的结果:

  • 用户完全关闭活动。如果用户将活动从“最近”屏幕上滑下,从活动中向上导航或退出活动,用户可以完全关闭该活动。在这些情况下的假设是用户已永久性地离开活动,如果他们再次打开活动,他们将期望从干净状态开始。

  • 用户旋转手机或将该活动置于后台,然后返回。例如,用户执行搜索,然后按主页按钮或接听电话。当他们返回到搜索活动时,他们希望能够像以前一样找到搜索关键字和搜索结果。

要在任何情况下实现复杂数据结构的行为,请一起使用本地持久性,ViewModel类和 onSaveInstanceState()方法。这些方法中的每一种都存储活动中使用的不同类型的数据。

  • 本地持久性:如果您打开并关闭活动,则存储您不想丢失的所有数据。
    • 示例:歌曲对象的集合,其中可能包含音频文件和元数据。
  • ViewModel:在内存中存储显示关联的UI控制器所需的所有数据。
    • 示例:最近搜索的歌曲对象和最近的搜索查询。
  • onSaveInstanceState():存储少量数据,以便在系统停止时轻松地重新加载活动状态,然后重新创建UI控制器。而不是在这里存储复杂的对象,将复杂的对象保存在本地存储中,并为这些对象存储唯一的ID onSaveInstanceState()
    • 例如:存储最近的搜索查询。

作为一个例子,考虑一个活动,可以让你搜索你的歌曲库。以下是应如何处理不同的事件:

当用户添加歌曲时,ViewModel立即委托人在本地保存这些数据。如果这首新添加的歌曲应该显示在用户界面中,则还应更新ViewModel对象中的数据以反映歌曲的添加。请记住从主线程执行所有数据库插入操作。

当用户搜索歌曲时,无论您从UI控制器的数据库加载的任何复杂歌曲数据都应立即存储在该ViewModel 对象中。您还应该将搜索查询本身保存在ViewModel对象中。

当活动进入后台时,系统调用 onSaveInstanceState()。您应该将搜索查询保存在 onSaveInstanceState()包中。这些少量的数据很容易保存。这也是将活动恢复到当前状态所需的全部信息。

恢复复杂的状态:重新组装


当用户返回活动时,有两种可能的方案来重新创建活动:

  • 该活动在系统停止后重新创建。该活动将查询保存在一个 onSaveInstanceState()包中,并将查询传递给ViewModel。在ViewModel看到它已经高速缓存任何搜索结果,和代表加载搜索结果,使用给定的搜索查询。
  • 该活动是在配置更改后创建的。该活动将查询保存在一个 onSaveInstanceState()包中,并且ViewModel已经将搜索结果缓存。您将onSaveInstanceState()包中的查询传递 给ViewModel,它确定它已经加载了必要的数据,并且不需要重新查询数据库。

注意:当一个活动最初创建时,该onSaveInstanceState()包不包含任何数据,并且该ViewModel对象为空。当你创建 ViewModel对象时,你传递一个空的查询,它告诉ViewModel对象没有要加载的数据。因此,活动以空状态开始。

根据您的活动实施情况,您可能根本无需使用 onSaveInstanceState()。例如,浏览器可能会将用户带回到他们退出浏览器之前所查看的确切网页。如果您的活动按照这种方式运行,您可以放弃使用 onSaveInstanceState(),而是在本地持久化所有内容。在歌曲搜索示例中,这可能意味着将最近的查询保留在共享首选项中。

此外,当您从意图打开活动时,无论是在配置更改还是系统恢复活动时,这些附加配件都会交付给活动。如果搜索查询作为意图额外传入,则可以使用额外捆绑包而不是 onSaveInstanceState() 捆绑包。

在这两种情况下,您仍然会使用a ViewModel来避免配置更改期间从数据库重新加载数据的浪费周期。

你可能感兴趣的:(Saving UI States(保存UI状态))