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
相关产品推荐
相关产品推荐

