ViewModel能替代onSaveInstanceState么?

ViewModel出现之前,处理横竖屏的最佳实践就是使用Activity的onSaveInstanceState()来保存Activity销毁之前的数据,在onCreate()或者onRestoreInstanceState()的时候取出数据。有了ViewModel之后,你可能会思考,这两种方式都有啥区别,是不是只用ViewModel就行了?

仁者见仁智者见智。这两种方式还是稍稍有些不一样的,我们简单做个回顾:

在Activity有可能会被系统销毁的情况下,系统会调用onSaveInstanceState()来供开发者保存数据,在Android P(level 28)的上,onSaveInstanceState()会在onStop()之后调用,在Android P之前,onSaveInstanceState()会在onStop()之前调用。他有一个Bundle类型的参数,你需要把数据都放到这个对象里。

“被系统销毁”,也就两种情况:

  • 发生configuration change(类似横竖屏)
  • Activity切换到后台,因为系统资源限制被杀掉。

发生configuration change的时候,Activity立马销毁,然后又立马重建。Activity切换到后台被杀掉,那么用户切换回来的时候,Activity还是得重建。Activity重新创建的时候,系统会把之前保存的Bundle再传回来处理。Activity可以在onCreate(Bundle)中获取这个Bundle,也可以在onRestoreInstanceState(Bundle)中获取,两个方法都会被调用到,你可以选择其中一个处理,区别就是onCreate只要建立新的Activity实例的时候就会运行,参数可能会空。onRestoreInstanceState则是专门对应onSaveInstanceState的,参数非空。

但是我还是推荐使用onCreate像下面这样去处理:

因为你保存的数据常常和ViewModel里的东西是相关的,在onRestoreInstanceState里往往不方便。

Android官方文档里说,onSaveInstanceState里尽量存一些简单的,轻量化数据,因为这些数据是可以跨进程的,应用在后台进程被杀掉,重新打开的时候onSaveInstanceState保存的数据也可获得。如果你存些复杂的数据,序列化和反序列化,会占用主线程很多时间。

总结一下,有他们的区别在以下几个方面:

  • 设计思路。ViewModel用来将UI和数据进行分离的,降低了耦合度。onSaveInstanceState专门用来恢复Activity被系统销毁前的UI数据的。
  • 适用范围。ViewModel只能处理configuration changes。onSaveInstanceState能处理各种Activity被系统销毁的情况,ViewModel能处理的范围是他的子集。
  • 数据大小。ViewModel能存储各种的大量数据。onSaveInstanceState只能存储基本类型,字符串和其他能序列化的类型。
  • 生命周期。onSaveInstanceState在进程被杀死后也可保存,ViewModel不行。

官方文档Android团队博客都有讲述如何保存UI实例状态的,他们讲的更详细一些,而且还涉及到了持久化存储方式,比如SharedPreference和数据库。基本上可以覆盖所有的情况了。

对于中小型项目,我个人把整个流程简化了一下,作为自己的最佳实践:

使用ViewModel来处理configuration change。抛弃onSaveInstanceState/onRestoreInstanceState,因为他们只用来存取简单的关键数据,不如用Intent来代替,启动Activity的时候(startActivity)不是要传一个Intent嘛,我们把关键数据放到这个Intent里,这样Activity每次onCreate都能获取到关键数据了,而且“被系统销毁”的时候,这个Intent你还能获取到(包括进程被杀)。

你觉得这样如何?

发表评论

电子邮件地址不会被公开。