将序列化ArrayList存储到SharedPreferences——取出时列表为空
嘿,这个问题我之前帮朋友排查过,大概率是SharedPreferences存储集合的方式出了问题——毕竟SP本身对集合的支持有点“挑剔”,咱们一步步来解决:
SharedPreferences只能存储基本数据类型、String,以及String类型的Set。如果直接把序列化后的ArrayList对象存进去(哪怕转成String),很容易因为序列化/反序列化过程中的异常导致取出为空,或者根本没存进去。
方案1:用SP原生支持的StringSet来存(推荐,最简单)
这是最稳妥的方式,不用搞复杂的序列化,直接把ArrayList转成HashSet存储,取出来再转回ArrayList就行:
存储代码
// 先把SparseBooleanArray转成ArrayList<String>(确保这一步没问题,先打印size确认有数据) SparseBooleanArray checkedPositions = yourListView.getCheckedItemPositions(); ArrayList<String> selectedItems = new ArrayList<>(); List<String> yourDataSource = ...; // 你的ListView数据源,比如从资源或接口来的列表 for (int i = 0; i < checkedPositions.size(); i++) { int pos = checkedPositions.keyAt(i); if (checkedPositions.valueAt(i)) { selectedItems.add(yourDataSource.get(pos)); } } // 存到SharedPreferences SharedPreferences sp = getSharedPreferences("UserPrefs", MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); editor.putStringSet("registered_selections", new HashSet<>(selectedItems)); editor.apply(); // 一定要用apply()或commit()提交修改!
取出代码
SharedPreferences sp = getSharedPreferences("UserPrefs", MODE_PRIVATE); // 第二个参数是默认值,避免null Set<String> savedSet = sp.getStringSet("registered_selections", new HashSet<>()); ArrayList<String> retrievedItems = new ArrayList<>(savedSet);
方案2:如果必须用序列化(比如暂时不想改太多逻辑)
如果一定要坚持序列化的方式,那得把ArrayList转成Base64编码的字符串再存,因为SP存普通的序列化字节数组转String可能会有编码问题:
存储工具方法
public static void saveSerializedList(SharedPreferences sp, String key, ArrayList<String> list) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(list); oos.flush(); oos.close(); // 转成Base64字符串,避免乱码 String encoded = Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT); sp.edit().putString(key, encoded).apply(); } catch (IOException e) { e.printStackTrace(); // 这里可以加日志,排查序列化失败原因 } }
取出工具方法
@SuppressWarnings("unchecked") public static ArrayList<String> getSerializedList(SharedPreferences sp, String key) { ArrayList<String> result = new ArrayList<>(); String encoded = sp.getString(key, null); if (encoded == null) { return result; } try { byte[] decodedBytes = Base64.decode(encoded, Base64.DEFAULT); ByteArrayInputStream bis = new ByteArrayInputStream(decodedBytes); ObjectInputStream ois = new ObjectInputStream(bis); result = (ArrayList<String>) ois.readObject(); ois.close(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); // 反序列化失败的话,这里会打日志 } return result; }
几个关键排查点
- 确认SparseBooleanArray转ArrayList的过程没问题:存之前打印
selectedItems.size(),看看是不是真的有数据,别一开始转出来就是空的。 - 一定要提交修改:存的时候必须调用
apply()或commit(),不然SP根本不会保存你的修改! - 检查反序列化的异常:如果用方案2,一定要看日志里有没有
IOException或ClassNotFoundException,这大概率是导致取出为空的原因。
内容的提问来源于stack exchange,提问作者Shox2711
相关产品推荐
相关产品推荐

