从Android应用程序发出大型网络请求时避免OutOfMemory异常

时间:2012-02-29 09:03:52

标签: android out-of-memory

我正在开发一个应用程序,在第一次启动时,我预计会以​​JSON格式下载大量数据(例如10-20 MB)。所有这些数据都在一个网络请求中传输(原因是数据是按请求动态生成的)。 fllowing代码在接收数据(in builder.append())时抛出OOM异常:

  public static String readToString(InputStream stream) throws IOException {
    BufferedReader in = null;
    StringBuilder builder = new StringBuilder();
    in = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
    char[] buffer = new char[1024];
    int read = 0;
    while ((read = in.read(buffer, 0, 1024)) > 0) {
      builder.append(buffer, 0, read);
    }
    in.close();
    return builder.toString();
  }

我该怎么做才能避免此错误?我正在考虑尝试将数据保存到临时文件然后处理它。但我不确定它是否会起作用。 另一种可能性似乎是将网络IO分为两部分:第一部分,应用程序接收有关应下载内容的数据,第二部分实际下载数据。

有什么建议吗?

2 个答案:

答案 0 :(得分:3)

按照您的第一个想法 - 将数据保存到临时文件(请使用SD卡。内部存储空间中的20mb太大)。您首先需要打开下载连接。

InputStream is = URL("your_request_string").openStream();

然后在sdcard中创建一个新文件

File f = new File(Environment.getExternalStorageDirectory(), "temp.dat");

使用新创建的文件,打开OutputStream。

FileOutputStream = new FileOutputStream(f);

您现在可以使用这段代码进行转移:

public static void CopyStream(InputStream is, OutputStream os) {
    final int buffer_size=8192;
    try
    {
        byte[] bytes=new byte[buffer_size];
        for(;;)
        {
          int count=is.read(bytes, 0, buffer_size);
          if(count==-1)
              break;
          os.write(bytes, 0, count);
        }
    }
    catch(Exception ex){}
}

答案 1 :(得分:1)

从API 11开始,有http://developer.android.com/reference/android/util/JsonReader.html用于读取Json数据流而不分配整个大字符串。

对于以前的版本,有大量第三方JSON库提供基于事件的流读取功能。