You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅使用saveInstanceState替代SharedPreference处理游戏旋转时分数保存

问题分析与解决

你的代码中每次启动onCreate都会从SharedPreference读取分数,覆盖了saveInstanceState恢复的值,这是导致只用saveInstanceState失效的核心原因。同时你还保留了所有SharedPreference的写入逻辑,进一步干扰了状态恢复流程。

修改步骤

  1. 删除所有SharedPreference相关的代码(包括初始化、读取、写入操作)
  2. 在onCreate中优先从savedInstanceState恢复count值,没有则初始化为0
  3. 恢复count后同步更新UI(文本内容、颜色)和按钮可用性状态
  4. 保留onSaveInstanceState的逻辑,确保旋转时保存当前分数

修改后的完整代码

import android.graphics.Color
import android.media.MediaPlayer
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    override fun onStart() {
        super.onStart()
        Log.i("TAG", "onStart")
    }

    var count = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Log.i("TAG", "onCreate")

        val scoreBtn = findViewById<Button>(R.id.btn_score)
        val stealBtn = findViewById<Button>(R.id.btn_steal)
        val resetBtn = findViewById<Button>(R.id.btn_reset)
        val resultTv = findViewById<TextView>(R.id.result)

        // 从savedInstanceState恢复count,没有则初始化为0
        if (savedInstanceState != null) {
            count = savedInstanceState.getInt("MyInt", 0)
        }

        Log.i("TAG", "当前分数: $count")

        // 初始化UI状态
        resultTv.text = count.toString()
        check(count, resultTv)
        checkBounds(scoreBtn, stealBtn)

        var mediaPlayer = MediaPlayer.create(this, R.raw.success_1_6297)
        if (count == 15) {
            mediaPlayer.start()
        }

        scoreBtn.setOnClickListener {
            count++
            resultTv.text = count.toString()
            check(count, resultTv)
            checkBounds(scoreBtn, stealBtn)

            if (count == 15) {
                mediaPlayer.start()
            }
        }

        stealBtn.setOnClickListener {
            count--
            resultTv.text = count.toString()
            check(count, resultTv)
            checkBounds(scoreBtn, stealBtn)
        }

        resetBtn.setOnClickListener {
            count = 0
            resultTv.text = count.toString()
            check(count, resultTv)
            checkBounds(scoreBtn, stealBtn)
        }
    }

    fun check(incrementNumber: Int, result: TextView) {
        result.setTextColor(
            when {
                incrementNumber >= 10 -> Color.GREEN
                incrementNumber >= 5 -> Color.BLUE
                else -> Color.BLACK
            }
        )
    }

    // 把checkBounds改为带参数的函数,避免依赖局部变量
    fun checkBounds(scoreBtn: Button, stealBtn: Button) {
        scoreBtn.isEnabled = count < 15
        stealBtn.isEnabled = count > 0
    }

    override fun onSaveInstanceState(savedInstanceState: Bundle) {
        super.onSaveInstanceState(savedInstanceState)
        // 保存当前分数到Bundle
        savedInstanceState.putInt("MyInt", count)
    }

    // 可选:也可以在onRestoreInstanceState中恢复,但onCreate中已经处理,这里可以删除或者保留
    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        super.onRestoreInstanceState(savedInstanceState)
        count = savedInstanceState.getInt("MyInt", 0)
        // 如果保留这个方法,需要重新更新UI和按钮状态
        val resultTv = findViewById<TextView>(R.id.result)
        val scoreBtn = findViewById<Button>(R.id.btn_score)
        val stealBtn = findViewById<Button>(R.id.btn_steal)
        resultTv.text = count.toString()
        check(count, resultTv)
        checkBounds(scoreBtn, stealBtn)
    }
}

关键说明

  • 状态恢复优先级:在onCreate中先判断savedInstanceState是否存在,存在则优先恢复,确保旋转后的分数正确
  • UI同步:恢复count后必须立即更新TextView文本、颜色和按钮可用性,保证界面状态和数据一致
  • 移除SharedPreference:完全删除SharedPreference相关代码,避免和saveInstanceState的状态冲突
  • checkBounds优化:改为带参数的函数,避免依赖onCreate中的局部变量,提升代码健壮性

内容的提问来源于stack exchange,提问作者ACN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:35:03