【问题标题】:Out of memory exception using gson + volley when doing gson.fromJson();执行 gson.fromJson(); 时使用 gson + volley 出现内存不足异常;
【发布时间】:2014-10-06 06:19:31
【问题描述】:

我正在使用 volley 和 gson 读取一个非常大的 json 文件。我看到我需要使用输入流来克服这个问题,但是如何从网络响应创建输入流?

我已经粘贴了 gson 请求类,它正在从 get 请求中获取响应

public class GsonRequest<T> extends Request<T[]> {

private final Gson gson;
private final Class<T[]> clazz;
private final Map<String, String> headers;
private final Listener<T[]> listener;

public GsonRequest(int method, String url, Class<T[]> clazz,
        Map<String, String> headers, Listener<T[]> listener,
        ErrorListener errorListener) {
    super(method, url, errorListener);

    GsonBuilder gsonBuilder = new GsonBuilder();

    this.gson = gsonBuilder.create();
    this.clazz = clazz;
    this.headers = headers;
    this.listener = listener;
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    return headers != null ? headers : super.getHeaders();
}

@Override
protected void deliverResponse(T[] response) {
    listener.onResponse(response);
}

@Override
protected Response<T[]> parseNetworkResponse(NetworkResponse response) {
    try {

        String json = new String(response.data,
                HttpHeaderParser.parseCharset(response.headers));
        // Log.e("Response", json.toString());
        T[] t = gson.fromJson(json, clazz);

        return Response.success(t,
                HttpHeaderParser.parseCacheHeaders(response));

    } catch (UnsupportedEncodingException e) {
        Log.e("Error", "UnsupportedEncodingException");

        return Response.error(new ParseError(e));
    } catch (JsonSyntaxException e) {
        Log.e("Error", "JsonSyntaxException");

        return Response.error(new ParseError(e));
    }

}

}

我的json数据格式

[
   {
        "salary": "Best In Industry",
        "companyProfile": "string",
        "tags": [
            "mtech"
        ],
    }, {
        "salary": "Best In Industry",
        "companyProfile": "string",
        "tags": [     
            "be/btech",
        ],
     }
]

【问题讨论】:

    标签: android gson android-volley android-networking


    【解决方案1】:

    阅读示例 此代码读取包含消息数组的 JSON 文档。它以流的形式逐步遍历数组元素,以避免将完整的文档加载到内存中。它很简洁,因为它使用 Gson 的对象模型来解析单个消息:

    public List<Message> readJsonStream(InputStream in) throws IOException {
        JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
        List<Message> messages = new ArrayList<Message>();
        reader.beginArray();
        while (reader.hasNext()) {
            Message message = gson.fromJson(reader, Message.class);
            messages.add(message);
        }
        reader.endArray();
        reader.close();
        return messages;
    }
    

    编写示例

    镜像上面的代码,这会编写一个包含消息数组的 JSON 文档。它得益于流式传输的内存效率和对象模型的简洁性:

    public void writeJsonStream(OutputStream out, List<Message> messages) throws IOException {
        JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, "UTF-8"));
        writer.setIndent("  ");
        writer.beginArray();
        for (Message message : messages) {
            gson.toJson(message, Message.class, writer);
        }
        writer.endArray();
        writer.close();
    }
    

    参考链接https://sites.google.com/site/gson/streaming

    【讨论】:

    • 嘿,谢谢!我已经看到了,但是如何从响应中创建输入流。
    • 这基本上是为了数组响应。你有什么 json 结构?
    • 所以,最主要的是不要使用字符串来绑定响应。在 writeJsonStream() 方法中,您有一个类似于 List 消息的 JsonArray。创建一个模型以在数组索引处解析 JsonObject 并将其替换为 Message.class
    • 如果我不将响应绑定到字符串,如何存储它
    • 您必须忘记您正在使用的方法。仔细阅读我从第一行附加的链接。您正在执行对象模型访问,但现在我们必须流式访问。研究 readJsonStream() 做了什么。只需花一些时间在上面,我相信你会在那篇文章中得到解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2016-11-17
    • 2015-07-11
    相关资源
    最近更新 更多