安卓开发:SharedPreferences存取String与Int数据时,点击获取按钮无法回填已存Int值
问题根因
- 核心逻辑错误:在
Get方法中判断到Numb键存在时,完全没有读取SharedPreferences中存储的int值,反而硬编码给number控件设置了固定值"0",自然无法取回保存的数字。 - 常见踩坑点:Android中
TextView.setText()没有直接接收int数值的重载方法——如果直接把读取到的int值传给setText(),系统会将这个int值识别为字符串资源ID,尝试查找对应资源时会抛出Resources$NotFoundException异常,这也是很多人无法正确把存储的int值回填到文本框的核心原因。 - 冗余逻辑:在
onCreate、Get、clear方法中重复初始化控件、重复获取SharedPreferences实例,既增加无意义的性能消耗,也容易造成逻辑混乱。 - 潜在崩溃风险:
Save方法中直接调用Integer.parseInt()解析输入框内容,如果用户未输入有效数字,会直接触发NumberFormatException导致应用崩溃。
修正实现
- 移除所有重复的控件初始化、SharedPreferences获取代码,仅在
onCreate中完成一次全局初始化即可。 - 修改
Get方法的数字读取逻辑:先通过sharedpreferences.getInt()取出存储的int值,使用String.valueOf()将其转为字符串后再设置给number控件,避免int值被误判为资源ID。 - 对数字输入框的解析逻辑增加非空校验,规避崩溃风险。
修正后的代码示例
public class MainActivity extends AppCompatActivity { SharedPreferences sharedpreferences; TextView name; TextView email; TextView number; public static final String Name = "nameKey"; public static final String Email = "emailKey"; public static final String Numb = "numbKey"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 全局统一初始化控件,无需在其他方法重复调用 name = findViewById(R.id.etName); email = findViewById(R.id.etEmail); number = findViewById(R.id.number); // 全局统一获取SharedPreferences实例 sharedpreferences = getSharedPreferences("mypref", Context.MODE_PRIVATE); // 启动时自动回填已存储的本地数据 if (sharedpreferences.contains(Name)) { name.setText(sharedpreferences.getString(Name, "")); } if (sharedpreferences.contains(Email)) { email.setText(sharedpreferences.getString(Email, "")); } if (sharedpreferences.contains(Numb)) { number.setText(String.valueOf(sharedpreferences.getInt(Numb, 0))); } Toast.makeText(getApplicationContext(),"It just saves the data",Toast.LENGTH_SHORT).show(); } public void Save(View view) { String n = name.getText().toString().trim(); String e = email.getText().toString().trim(); // 增加输入校验,避免空值/非数字导致崩溃 String inputNum = number.getText().toString().trim(); if (TextUtils.isEmpty(inputNum)) { Toast.makeText(this, "请输入有效数字", Toast.LENGTH_SHORT).show(); return; } int numb = Integer.parseInt(inputNum); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Name, n); editor.putString(Email, e); editor.putInt(Numb, numb); editor.apply(); // 相比commit,apply为异步写入,更推荐日常使用 Toast.makeText(getApplicationContext(),"Number was:"+numb,Toast.LENGTH_SHORT).show(); } public void Get(View view) { // 直接使用全局初始化的控件和SharedPreferences实例即可 if (sharedpreferences.contains(Name)) { name.setText(sharedpreferences.getString(Name, "")); } if (sharedpreferences.contains(Email)) { email.setText(sharedpreferences.getString(Email, "")); } if (sharedpreferences.contains(Numb)) { // 正确读取存储的int值,转为字符串后设置给控件 int savedNum = sharedpreferences.getInt(Numb, 0); number.setText(String.valueOf(savedNum)); } } public void clear(View view) { // 清除SharedPreferences存储的内容,同时清空控件显示 sharedpreferences.edit().clear().apply(); name.setText(""); email.setText(""); number.setText(""); } }
说明:原来的
editor.commit()是同步写入磁盘,适合需要确保写入成功的极端场景,日常开发推荐使用editor.apply(),它会先更新内存值再异步写盘,不会阻塞主线程。
内容的提问来源于stack exchange,提问作者Gth6
相关产品推荐
相关产品推荐

