Android assets目录下HashMap读写实现及替代方案咨询
问题解答
问题1:基于Assets InputStream完成HashMap读写的方案
首先明确两个基础前提:
ObjectInputStream本身支持封装任意InputStream实例,不需要是本地文件流,直接用getAssets().open()返回的输入流构造即可完成读取操作- assets是APK打包后的只读目录,运行时无法写入任何内容,因此更新后的HashMap本来就不能存回assets路径,写操作无需操作assets相关流
读取assets中预置序列化HashMap的示例代码如下:
HashMap<String, Object> initMap; try (ObjectInputStream ois = new ObjectInputStream(getAssets().open("pre_map.bin"))) { initMap = (HashMap<String, Object>) ois.readObject(); } catch (IOException | ClassNotFoundException e) { // 异常兜底,初始化空HashMap initMap = new HashMap<>(); }
注意:使用Java原生序列化时建议显式声明HashMap存储对象的serialVersionUID,避免APP版本升级后出现反序列化失败的问题
问题2:替代内外置存储的实现方案
有三类常用的实现方案可选,可根据数据量和业务场景选择:
- SharedPreferences存储:适合数据量较小的场景。可以将HashMap序列化后转为Base64字符串存入SP,或者直接拆分键值对存储(仅适用于value为基础类型/字符串的场景),示例代码如下:
// 保存更新后的HashMap到SP SharedPreferences sp = getSharedPreferences("app_data", MODE_PRIVATE); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(updatedMap); String mapBase64 = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT); sp.edit().putString("saved_hash_map", mapBase64).apply(); } catch (IOException e) { e.printStackTrace(); } // 从SP读取已保存的HashMap String cache = sp.getString("saved_hash_map", null); if (cache != null) { byte[] data = Base64.decode(cache, Base64.DEFAULT); try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) { HashMap<String, Object> savedMap = (HashMap<String, Object>) ois.readObject(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } - JSON序列化存储:兼容性优于Java原生序列化,可使用Gson等工具将HashMap转为JSON字符串后,存入SP或其他轻量存储介质,不存在serialVersionUID不匹配的问题
- SQLite数据库存储:适合数据量较大、需要频繁查询更新的场景,可单独建一张键值对表存储HashMap的所有条目,读写稳定性更高,也支持局部字段更新,无需每次全量序列化整个HashMap
内容的提问来源于stack exchange,提问作者t173_1304
相关产品推荐
相关产品推荐

