Saving UI States

来源:互联网 发布:pdf电子书资源 知乎 编辑:程序博客网 时间:2024/05/30 04:38

相对用户体验而言,如何保留当前UI界面的状态都是很关键的一部分,不管你做还是不做。不论用户是旋转屏幕,重启应用,或者系统关掉了应用,如何保持用户所期望的界面状态是很重要的。

当要保存少量且轻量的UI数据时,可以考虑使用onSaveInstanceState()。如果想要保存相对比较复杂的数据时,可以同时使用ViewModel对象,以及onSaveInstanceState(),以及持久化本地数据。

接下来将介绍如何去保存UI状态数据。

Manging simpler cases:onSaveInstanceState()

使用onSaveInstanceState()处理简单的场景
onSaveInstanceState()回调函数用于存储相对较少量的数据,以便在系统停止并稍后重新创建该控制器时轻松地重新加载UI控制器的状态,如Activity或Fragment。这个回调主要处理以下两种情况:
1. 由于内存的限制,系统会杀掉后台的应用进程
2. 配置变化,比如说屏幕旋转,修改输入语言等
以上两种情况意味着,系统在回调这个方法是,Activity被停止,但是还没有完全结束。举个例子,当用户离开应用几个小时后,系统会从内存中把相关的进程弹出,
系统会回调默认的onSaveInstanceState()实现来保存每个拥有ID的UI Controller。然后,当用户返回到应用时,系统将恢复之前保存的Activity状态。

注:有两种情况下onSaveInstanceState()不会被调用,一个是用户明确要关闭当前的Activity,另一个就是某些场景下直接调用onFinished()。

系统会自动保存和恢复大部分的UI数据;onSaveInstanceState()的默认实现中保存了Activity的视图树,比如EditText控件中的输入文本以及ListView控件当前滑动的列表项。开发过程中,我们可以通过重写onSaveInstanceState()回调方法,将一些自定义数据保存到Bundle中。如果您打算重写此方法以保存未被每个实体捕获的附加信息,应该调用默认实现,除非你准备自行保存每个实体的状态。

onSaveInstanceState()为保存大量数据而设计的,比如Bitmaps或者需要冗长的序列化和反序列化的复杂的数据结构。复杂的数据在序列化过程会消耗大量的内存。因为在设备配置发生变化的时候,这个过程是在主线程中执行的,长时间序列化会引起掉帧或者卡顿。因此,使用本地数据持久化来代替onSaveInstanceState()存储复杂的数据结构;比较好的一个方法就是在数据创建的时候就进行保存,然后使用onSaveInstanceState()保存对应数据的ID。

Managing more complex states : divide and conquer

使用分而治之的方法管理复杂的状态
当你需要比较复杂的数据结构需要在Activity结束时保存,可以通过多种不同存储方式实现,这样能更有效的保存和恢复这些数据。

用户可以通过两个比较常规的方式离开Activity,这两个方式会使用户期望得到不同的结果:
1. 用户完全关闭了Activity。如果用户将Activity从当前的屏幕中滑下,或者向上导航或返回当前Activity,都可以完全关闭这个Activity。在这种情况下,就可以假设用户想要拥有离开或推出当前Activity,当他们重新进入或打开这个Activity时,他们期望看到的是一个全新的页面,而不是之前的退出的状态。
2. 用户旋转手机或者将当前Activity切换至后台,然后再重新切回前台。举个例子,用户点击了搜索按钮然后点击了Home键,或者用户接听了一个电话。当返回后,用户期望搜索界面中保留着之前的输入,并显示和之前一样的搜索结果。

为了实现上述场景中复杂数据结构保存,可以结合使用本地持久化,ViewModel和onSaveInstanceState()方法。每种方法保存activity中不同类型的数据。

  • 本地持久化:保存那些不论你打开或关闭当前activity都不想遗漏的所有数据。
  • ViewModel:保存和UI Controller展示相关的所有数据(保存在内存中)。比如最近查询的歌曲或者搜索结果。
  • onSaveInstanceState():保存少量的便于快速加载Activity,当系统停止Activity后又重新重建。通过本地数据库保存复杂数据,然后通过onSaveInstanceState()保存对应的数据索引ID,比如保存最近的搜索结果。

以搜索歌曲库为例子,在一个Activity中,可以进行搜索歌曲库的功能,然后我们需要做那些操作来实现数据的保存与恢复:

当用户添加一首歌曲时,ViewModel快速实现数据的本地持久化,如果新加的歌曲需要在当前的页面中显示,就需要更新ViewModel响应该歌曲已经添加成功。记住所有的数据库操作在子线程中执行。

当用户搜索一首歌曲,不论歌曲的数据多复杂,都需要从数据库中加载到ViewModel中,搜索的数据也必须保存在ViewModel中。

当activity退至后台,系统会回调onSaveInstanceState()。需要在onSaveInstanceState()保存用户的查询ID。这个少量的数据容易存储。这也是activity显示到前台后需要显示的所有信息。

Restoring complex states:reassembling the pieces

恢复复杂的状态:组装相关数据
当用户重新返回Activity时,有两个可能的场景需要重新创建activity:

  • activity是有系统停止然后重建。activity将搜索的id保存在onSaveInstanceState()的bundle中,此时需要传给ViewModel,ViewModel发现没有缓存数据,然后就会通过所有去本地数据库加载搜索结果。
  • activity是有设备配置变化重建的。activity将搜索的id保存在onSaveInstanceState()的bundle中,此时需要传给ViewModel,ViewModel发现有缓存数据,然后就不需要去查询本地数据库了。

注:当activity被首次创建时,onSaveInstanceState()中的bundle数据为空,ViewModel数据也为空。当创建ViewModel时需要传递一个空的搜索id,告诉ViewModel不需要加载任何数据。因此activity将显示一个全新的状态。

基于activity的实现,也许不必在onSaveInstanceState()中保存任何数据。比如浏览器可能会将用户返回到之前退出的那个页面。如果你的activity实现了这个功能就可以不使用onSaveInstanceState,直接将数据进行本地持久化。在歌曲搜索的例子中,意味着持久化最近的搜查到Shared Preferences中。

另外,当你通过Intent启动一个Acitivity时,
无论是配置更改还是系统恢复Activity,都会将其附加Bundle交传给Activity。如果搜索查询是作为intent的额外信息传入的,则可以使用extras bundle而不使用onSaveInstanceState()bundle。

不论上述的哪一种场景,都需要使用ViewModel避免重复的从数据库中加载数据。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机支架不粘了怎么办 赌博把房子输了怎么办 当发现老公有外遇时怎么办 led灯带中间不亮怎么办 飘窗的天花板凸怎么办 一受委屈就爱哭怎么办 6岁儿童叛逆期怎么办 孩子高一了厌学怎么办 除上有肥胖纹怎么办 6岁不爱写作业怎么办 初中孩子不爱写作业怎么办 孩子上课走神写作业慢怎么办 孩子作业写得慢怎么办 4岁宝宝不写作业怎么办 小孩作业写得慢怎么办 3岁宝宝不写作业怎么办 小孩不写作业怎么办呀 作业没写完的人怎么办? 孩子不写作业家长该怎么办 做作业做得慢怎么办 高一作业写得慢怎么办 孩子做作业不认真怎么办 孩子不主动做作业怎么办 写作业静不下心怎么办 小孩不写作业怎么办啊 小孩子写作业爱磨蹭怎么办 孩子在学校不写作业怎么办 鳗鱼刺卡在喉咙怎么办 被小鱼刺卡住了怎么办 喉咙上卡了鱼刺怎么办 跟团出去受伤了怎么办 平安易宝冻结了怎么办 车的保险到期没有交怎么办 人保外地险出险怎么办 婚姻经营不下去了怎么办 他不爱我,我该怎么办 没有我你怎么办钢琴版 没有你怎么办严爵歌词 没有羊毛戳针该怎么办 没有我你该怎么办歌词 雌激素低子宫内膜薄怎么办