【问题标题】:OutOfMemory exception when converting object to Json through Gson通过 Gson 将对象转换为 Json 时出现 OutOfMemory 异常
【发布时间】:2017-09-27 11:00:04
【问题描述】:

我来了

java.lang.OutOfMemoryError

当我使用 Gson 将对象列表转换为 JSON 时,对于某些用户(并非总是如此)。请告诉我如何解决这个问题。

@Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if(myList != null && !myList.isEmpty()) {
            //exception at this line
            String myJson = new Gson().toJson(myList, myList.getClass());
            outState.putString(MY_LIST, myJson);
        }
        outState.putInt(NEXT_PAGE, getNextPage());
    }

myList 是我的自定义对象列表,列表大小为 400kb 到 600kb

【问题讨论】:

  • 检查 myList 的大小
  • @Stultuske 它的尺寸很大。但我必须转换大型列表。有什么办法吗?
  • myList 是普通列表吗? myList 中包含的对象类别是什么?
  • @HeikkiMäenpää 这是我的自定义对象列表,列表大小为 400kb 到 600kb
  • 你可以将单个对象转换为 JSON 没有任何麻烦吗?当一个对象的一个​​类型的成员具有对其所属对象的引用时,我已经看到 JSON 序列化陷入递归。

标签: java android json gson savestate


【解决方案1】:

这将取决于您的列表的大小。为什么不使用流式 API https://sites.google.com/site/gson/streaming

更具体一点,比如

public String writeListToJson(List myList) throws IOException {
    ByteArrayOutputStream byteStream =new ByteArrayOutputStream();
    OutputStreamWriter outputStreamWriter=new OutputStreamWriter(byteStream ,"UTF-8");
    JsonWriter writer = new JsonWriter(outputStreamWriter);
    writer.setIndent("  ");
    writer.beginArray();
    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
    for (Object o : myList) {
        gson.toJson(o, o.class, writer);
    }
    writer.endArray();
    writer.close();
    return byteStream.toString("UTF-8");
}

【讨论】:

  • 如果要将最终结果转换为String,为什么还要使用流式传输JsonWriter?
  • @pskink 如果您看到 OP,他正在将“字符串”写回 outState outState.putString(MY_LIST, myJson); 这是 Gson 转换器,它不会一次性转换大列表,因此是 gson 的助手。所以他可以使用这个 util 类,通过 Gson 的 OOM 并根据需要使用字符串。
  • 好的,所以在你的方法中有 1) 大 myList 2) 大 ByteArrayOutputStream 必须存储 myList 内容和 3) 大 String 作为 byteStream.toString 的结果问题是如果出现OOM 异常,这三个大数据对象将如何提供帮助?
  • 他已经有一个大的myList,将它存储在Stream中不是问题,使用Gson将大列表转换为json字符串是OOM的原因。不持有这些物品
【解决方案2】:

myList 是我的自定义对象列表,列表大小为 400kb 到 600kb

NOT 将其置于已保存的实例状态Bundle。 OutOfMemoryError 只是您的担心之一。很多时候你会因为FAILED BINDER TRANSACTION 而崩溃,因为你的应用程序中所有同时进行的 IPC 事务有 1MB 的限制。

如果您正在尝试处理配置更改,请使用其他东西来保存此信息:

  • 保留的片段
  • onRetainNonConfigurationInstance()
  • ViewModel 来自 Android 架构组件
  • 等

如果您尝试处理进程终止/应用程序重启,请将标识符置于已保存的实例状态Bundle,这将允许您从持久存储(数据库、纯文件等)重新加载此列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 2017-08-11
    • 1970-01-01
    • 2020-11-27
    • 2018-01-20
    • 1970-01-01
    • 2018-02-21
    相关资源
    最近更新 更多