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

SharedPreferences与TextView配合失效问题排查求助

问题分析与修复方案

我仔细看了你的代码,核心问题出在**onResume的执行逻辑和初始化优先级**上,导致你从Bundle拿到的初始值被SharedPreferences的默认值覆盖了。让我一步步拆解并给出修复方案:

为什么会出现默认值覆盖的情况?

  • 页面首次启动时,onCreate里你从Bundle拿到初始的calorieCount(比如2100)并设置给了remainingCalories,但紧接着onResume会执行——这时候还没点击过保存按钮,SharedPreferences里没有sessionCalories这个键,所以会返回你设置的默认空字符串,直接把刚设置的2100覆盖掉了。
  • 就算之前保存过值,每次页面切回前台,onResume的无条件赋值逻辑也可能和其他操作冲突。

修复步骤

我们需要调整逻辑,让页面初始化时优先读取持久化数据,只有无保存数据时才用Bundle的初始值,同时统一数据加载逻辑避免重复代码。

1. 抽统一的数据加载方法

把读取SharedPreferences和更新UI的逻辑抽成一个方法,方便onCreate和onResume复用:

private void loadSavedCalories() {
    // 如果后续多类需要访问,建议换成全局SharedPreferences(见下文优化)
    SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);
    // 优先取保存值,无保存值则用Bundle传过来的初始值作为默认
    String savedCalories = mPrefs.getString("sessionCalories", calorieCount);
    calorieCount = savedCalories; // 更新全局变量,确保后续操作基于最新值
    remainingCalories.setText(savedCalories);
}

2. 修改onCreate初始化逻辑

替换原来直接设置TextView的代码,调用统一加载方法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_calorie_tracker);
    getSupportActionBar().setDisplayShowHomeEnabled(true);

    Bundle extras = getIntent().getExtras();
    age = extras.getString("age");
    calorieCount = extras.getString("calories");
    System.out.println(age + ":" + calorieCount);

    itemName = findViewById(R.id.productNameCalorieTracker);
    kCal = findViewById(R.id.calorie_kcal);
    submitBtn = findViewById(R.id.submit_calorie);
    remainingCalories = findViewById(R.id.remainingCalorieCount);

    // 替换原setText,用统一方法加载数据
    loadSavedCalories();

    submitBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 增加输入合法性校验,避免NumberFormatException
            if (TextUtils.isEmpty(remainingCalories.getText()) || TextUtils.isEmpty(kCal.getText())) {
                return;
            }
            try {
                int currentCount = Integer.parseInt(remainingCalories.getText().toString());
                int enteredAmount = Integer.parseInt(kCal.getText().toString());
                calorieCount = String.valueOf(currentCount - enteredAmount);
                remainingCalories.setText(calorieCount);

                // 保存数据到SharedPreferences
                SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);
                SharedPreferences.Editor editor = mPrefs.edit();
                editor.putString("sessionCalories", calorieCount);
                editor.apply(); // 推荐用apply()异步提交,比commit()更高效
            } catch (NumberFormatException e) {
                // 处理非数字输入的情况,比如提示用户
                Toast.makeText(CalorieTracker.this, "请输入有效数字", Toast.LENGTH_SHORT).show();
            }
        }
    });
}

3. 简化onResume逻辑

现在onResume只需要调用统一加载方法即可,确保页面回到前台时数据是最新的:

@Override
protected void onResume() {
    super.onResume();
    loadSavedCalories();
}

针对多类复用的额外优化

因为你提到后续多个类都会用到这个功能,当前Activity私有的getPreferences(MODE_PRIVATE)无法被其他类访问,建议换成全局SharedPreferences:

// 保存时
SharedPreferences mPrefs = getSharedPreferences("CalorieGlobalPrefs", MODE_PRIVATE);
// 读取时(其他类可通过Context调用:context.getSharedPreferences("CalorieGlobalPrefs", MODE_PRIVATE))
SharedPreferences mPrefs = getSharedPreferences("CalorieGlobalPrefs", MODE_PRIVATE);

这样其他类就能直接读取和修改这个卡路里数值了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:18:03