
本文介绍如何通过 onSaveInstanceState 和 onRestoreInstanceState 机制,在 Activity 因配置变更(如横竖屏切换)重建时,准确保存并恢复 9 个动态设置为 "X" 或 "O" 的按钮文本内容,避免游戏状态丢失。
本文介绍如何通过 `onsaveinstancestate` 和 `onrestoreinstancestate` 机制,在 activity 因配置变更(如横竖屏切换)重建时,准确保存并恢复 9 个动态设置为 "x" 或 "o" 的按钮文本内容,避免游戏状态丢失。
在实现井字棋(Tic-Tac-Toe)类 UI 时,常使用 Button[] buttons = new Button[9] 表示棋盘格,并在用户点击后动态设置其文本为 "X" 或 "O"。由于 Android 在屏幕旋转时会销毁并重建 Activity,若不主动保存视图状态,所有按钮的文本将重置为空,导致游戏进度丢失。
核心思路是:不依赖 SharedPreferences,而应使用系统提供的 Bundle 生命周期机制 —— onSaveInstanceState() 用于序列化当前状态,onCreate() 或 onRestoreInstanceState() 用于反序列化还原。SharedPreferences 更适合长期持久化(如用户偏好),而屏幕旋转属于瞬时配置变更,Bundle 是更轻量、更标准且性能更优的选择。
✅ 推荐实现方式(简洁可靠)
定义状态表示格式:将 9 个按钮的文本统一编码为长度为 9 的字符串(或字符串数组),空格用
"-"占位,便于解析。例如:"X,-,O,X,O,-,-,X,O"。-
保存状态(
onSaveInstanceState):@Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); StringBuilder stateBuilder = new StringBuilder(); for (int i = 0; i -
恢复状态(
onCreate中):@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化 buttons 数组(通过 findViewById 等方式) initButtons(); // 此处需确保 buttons 已正确赋值 // 恢复按钮状态 if (savedInstanceState != null) { String savedState = savedInstanceState.getString("board_state"); if (savedState != null) { String[] parts = savedState.split(","); for (int i = 0; i
⚠️ 重要注意事项:
- 确保
buttons数组在onCreate()中早于状态恢复逻辑完成初始化(即initButtons()必须先执行),否则会出现NullPointerException; - 不要在
onSaveInstanceState中保存View对象本身(如buttons[i]),只保存可序列化的数据(字符串、整型等); - 若使用
Fragment,同样适用该机制,但需注意setRetainInstance(true)已废弃,推荐统一使用ViewModel+SavedStateHandle(现代替代方案); - 此方案不涉及
SharedPreferences,因其读写有 I/O 开销,且对瞬时状态过度持久化反而影响性能与语义清晰度。
通过上述方式,你不仅能精准还原每个按钮的文本与颜色,还能保持游戏逻辑(如 activePlayer、gameState[])与 UI 状态严格同步,为后续扩展(如撤销、AI 对战)打下坚实基础。










