使用Post从服务器读取大型xml文件时内存不足

时间:2013-01-22 11:03:27

标签: android

我正在使用以下代码从服务器获取xml文件,并且由于重型和大型xml文件,它崩溃并显示内存不足问题。

 public class Connect {

   static BufferedReader in=null;
   String result=null;
   Context context;
   //Establish connection with web server
      public String HTTPConnect(String uri1,List<NameValuePair> list,Context context)
      {

    this.context=context;
    try {

        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(uri1);

        if(list!=null)
        {
        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list);

        httpPost.setEntity(formEntity);
        }

        HttpResponse httpResponse = httpClient.execute(httpPost);
       in = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
        StringBuffer sb = new StringBuffer("");
        String line = "";
        String NL = System.getProperty("line.separator");

        long heapSize = Runtime.getRuntime().totalMemory();

        if(in!=null)
        {
            while ((line = in.readLine()) != null) {//crasheg here
              sb.append(line + NL);
            }
            in.close();
        }

        result = sb.toString();


}
    catch(UnsupportedEncodingException e)
    {
        String err = (e.getMessage()==null)?"Cant connect to server":e.getMessage();

        ShowDialog();
    }
    catch (MalformedURLException e) {
        String err = (e.getMessage()==null)?"Malformed Exception":e.getMessage();

        ShowDialog();
     } 
     catch(Exception ex)
     {

         String err = (ex.getMessage()==null)?"NetworkConnectionException":ex.getMessage();

         ShowDialog();
     }
    finally {
        if (in != null) {
            try {
                    in.close();
             } catch (Exception ex) {
                 String err = (ex.getMessage()==null)?"Excepion":ex.getMessage();

                 ex.printStackTrace();

            }
        }

     }

    return result;

   }

我知道我正在使用String复制整个XML,并且由于文件繁重,因此崩溃了。它在小型XML文件中运行良好,但是大型xml文件的替代方法是什么。我正在使用SAX解析器来解析这个xml文件。

[编辑] 下面是logcat:

 FATAL EXCEPTION: AsyncTask #4
 java.lang.RuntimeException: An error occured while executing doInBackground()
 at android.os.AsyncTask$3.done(AsyncTask.java:200)
 at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
 at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
 at java.util.concurrent.FutureTask.run(FutureTask.java:137)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
 at java.lang.Thread.run(Thread.java:1096)
 Caused by: java.lang.OutOfMemoryError
 java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:97)
 java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:136)
 java.lang.StringBuilder.append(StringBuilder.java:272)
 java.io.BufferedReader.readLine(BufferedReader.java:452)
 com.kxs.appitize.Connect.HTTPConnect(Connect.java:56)
 com.kxs.appitize.ListRestaurants$Asyn_rest.doInBackground(ListRestaurants.java:168)
 com.kxs.appitize.ListRestaurants$Asyn_rest.doInBackground(ListRestaurants.java:1)
 01-at android.os.AsyncTask$2.call(AsyncTask.java:185)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
  Activity com.kxs.appitize.TabsMainActivity has leaked window    com.android.internal.policy.impl.PhoneWindow$DecorView@44f4fb28 that was originally added here
 android.view.WindowLeaked: Activity com.kxs.appitize.TabsMainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44f4fb28 that was originally added here
 at android.view.ViewRoot.<init>(ViewRoot.java:247)
 at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
 at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
 at android.view.Window$LocalWindowManager.addView(Window.java:424)
 at android.app.Dialog.show(Dialog.java:241)
 at com.kxs.appitize.ListRestaurants$Asyn_rest.onPreExecute(ListRestaurants.java:156)
 at android.os.AsyncTask.execute(AsyncTask.java:391)
 at com.kxs.appitize.ListRestaurants.onCreate(ListRestaurants.java:133)
 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
 at android.app.ActivityThread.startActivityNow(ActivityThread.java:2503)
 at android.app.LocalActivityManager.moveToState(LocalActivityManager.java:127)
 at android.app.LocalActivityManager.startActivity(LocalActivityManager.java:339)
at com.kxs.appitize.TabGroupActivity.startChildActivity(TabGroupActivity.java:72)
  at com.kxs.appitize.ListCategories$1.onClick(ListCategories.java:109)
 at android.view.View.performClick(View.java:2408)
 at android.view.View$PerformClick.run(View.java:8816)
 at android.os.Handler.handleCallback(Handler.java:587)
  at android.os.Handler.dispatchMessage(Handler.java:92)
 at android.os.Looper.loop(Looper.java:123)     
 at android.app.ActivityThread.main(ActivityThread.java:4627)
 at java.lang.reflect.Method.invokeNative(Native Method)
 java.lang.reflect.Method.invoke(Method.java:521)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
 at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:0)

尝试使用inputStream来解析XML。 inputStrem不会增加Android堆栈大小,并且它可以防止大型String的OOM。我使用大型JSON也有同样的东西,现在,我使用Jackson直接从Stream解析JSON。

您可以找到用于解析XML的等效库。

答案 1 :(得分:0)

  

在String中复制整个XML并由于文件繁重

糟糕的主意。首先,您需要将xml缓存在临时目录中。它永远不应该在RAM中。

一旦你这样做,使用SAX来解析文件。在解析期间尽量不要将整个结构保留在RAM中,而是在一口大小的块中进行解析。