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

将序列化ArrayList存储到SharedPreferences——取出时列表为空

嘿,这个问题我之前帮朋友排查过,大概率是SharedPreferences存储集合的方式出了问题——毕竟SP本身对集合的支持有点“挑剔”,咱们一步步来解决:

先搞清楚核心问题:SharedPreferences不直接支持存序列化的ArrayList

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:09:28