因为业务原因, 我在安卓端实现了一个简单的富文本编辑器. 在初步实现后, 我将这个自定义的 RichEditor 放到了我们 App 的发帖界面中, 而发帖界面的复杂逻辑也引发了后续的问题.
界面回收与状态保持
我们的发帖界面可能唤起选图界面, 而图片处理往往需要消耗可观的内存. 在部分内存紧缺的机型上, 安卓系统为了保证选图界面的内存, 会将发帖界面回收并保存其状态, 在返回到发帖界面时又会将界面重建并恢复其控件状态.
安卓官方控件, 如 TextView, EditText 等控件在界面重建后, 其中的文本内容和光标位置都会被还原到重建前的状态, 而我的 RichEditor 却一片空白, 为啥?
关键方法
Activity/Fragment 的销毁和重建涉及到了两个重要的方法: onSaveInstanceState(Bundle)
和onRestoreInstanceState(Bundle)
, 在这两个方法中, 开发者可以自行存入当前界面的关键信息以便恢复界面状态(当然, Fragment + ViewPager 配套使用时会有一些问题, 相关资料大家可以上网查查).
View 的状态保存与重建与 Activity 类似, 但是实现过程稍有不同:
- Activity 通过 Bundle 对象保存关键值, 其存取采用 key-value 一一对应方式
- View 通过自定义的 SavedState 类型保存关键值, 其存取基于 Parcelable 实现
了解了两者的差别后, 我们来看看具体实践:
实践
一个简单的例子
1 | public class StateSavedView extends View { |
有以下几点需要注意:
- 状态的存取由 Parcelable 实现, 因此字段的存取顺序一定要保持一一对应
- 不要忘记调用父类方法, 否则会出错
- 这里保存的都是 UI 层的状态, 业务逻辑相关的状态千万不要放在这里, 否则很有可能引发一些隐蔽的 bug