在我的应用程序中,我以JSON的形式从服务器获取数据。数据大约为1.5 MB。该应用程序可以工作,但有时它会在从服务器获取OutOfMemoryError的数据时崩溃。
这是我的方法:
private String sendPostRequest(String url, List<NameValuePair> params)
throws Exception {
String ret = null;
BufferedReader bufferedReader = null;
HttpClient httpClient = new DefaultHttpClient();
HttpPost request = new HttpPost(url);
try {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params);
request.setEntity(entity);
HttpResponse response = httpClient.execute(request);
bufferedReader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
StringBuilder stringBuilder = new StringBuilder("");
StringBuilder stringBuilder2;
String line = "";
//String LineSeparator = System.getProperty("line.separator");
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
bufferedReader.close();
ret = stringBuilder.toString();
stringBuilder = null;
} catch (ClientProtocolException e) {
e.printStackTrace();
// TODO: report an error
} catch (IOException e) {
e.printStackTrace();
// TODO: report an error
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
// TODO Auto-generated catch block
}
}
}
return ret;
}
我尝试在使用后将StringBuilder设置为null但没有帮助。 我发布下面的logcat痕迹:
10-23 03:39:25.271: E/dalvikvm-heap(1011): Out of memory on a 4116282-byte allocation.
10-23 03:39:25.271: I/dalvikvm(1011): "AsyncTask #1" prio=5 tid=11 RUNNABLE
10-23 03:39:25.271: I/dalvikvm(1011): | group="main" sCount=0 dsCount=0 obj=0x417c5e88 self=0x2a1d1db8
10-23 03:39:25.271: I/dalvikvm(1011): | sysTid=1025 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=706552328
10-23 03:39:25.271: I/dalvikvm(1011): | state=R schedstat=( 3053328788 23773807212 6541 ) utm=241 stm=64 core=0
10-23 03:39:25.271: I/dalvikvm(1011): at java.lang.String.<init>(String.java:~422)
10-23 03:39:25.271: I/dalvikvm(1011): at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:642)
10-23 03:39:25.282: I/dalvikvm(1011): at java.lang.StringBuilder.toString(StringBuilder.java:663)
10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.datalayer.ServerConnect.sendPostRequest(ServerConnect.java:128)
10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.datalayer.ServerConnect.Sync(ServerConnect.java:61)
10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.datalayer.DBSync.Login(DBSync.java:59)
10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.doInBackground(SyncDBTask.java:52)
10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.doInBackground(SyncDBTask.java:1)
10-23 03:39:25.282: I/dalvikvm(1011): at android.os.AsyncTask$2.call(AsyncTask.java:287)
10-23 03:39:25.282: I/dalvikvm(1011): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
10-23 03:39:25.282: I/dalvikvm(1011): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
10-23 03:39:25.282: I/dalvikvm(1011): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
10-23 03:39:25.282: I/dalvikvm(1011): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
10-23 03:39:25.282: I/dalvikvm(1011): at java.lang.Thread.run(Thread.java:841)
10-23 03:39:25.282: W/dalvikvm(1011): threadid=11: thread exiting with uncaught exception (group=0x41465700)
10-23 03:39:25.292: I/Choreographer(1011): Skipped 30 frames! The application may be doing too much work on its main thread.
10-23 03:39:25.491: E/AndroidRuntime(1011): FATAL EXCEPTION: AsyncTask #1
10-23 03:39:25.491: E/AndroidRuntime(1011): java.lang.RuntimeException: An error occured while executing doInBackground()
10-23 03:39:25.491: E/AndroidRuntime(1011): at android.os.AsyncTask$3.done(AsyncTask.java:299)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
10-23 03:39:25.491: E/AndroidRuntime(1011): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.lang.Thread.run(Thread.java:841)
10-23 03:39:25.491: E/AndroidRuntime(1011): Caused by: java.lang.OutOfMemoryError
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.lang.String.<init>(String.java:422)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:642)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.lang.StringBuilder.toString(StringBuilder.java:663)
10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.datalayer.ServerConnect.sendPostRequest(ServerConnect.java:128)
10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.datalayer.ServerConnect.Sync(ServerConnect.java:61)
10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.datalayer.DBSync.Login(DBSync.java:59)
10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.doInBackground(SyncDBTask.java:52)
10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.doInBackground(SyncDBTask.java:1)
10-23 03:39:25.491: E/AndroidRuntime(1011): at android.os.AsyncTask$2.call(AsyncTask.java:287)
10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
10-23 03:39:25.491: E/AndroidRuntime(1011): ... 4 more
10-23 03:39:28.091: E/WindowManager(1011): Activity com.dzo.dispatchcrude.driverapp.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{4178fcb0 V.E..... R.....ID 0,0-479,96} that was originally added here
10-23 03:39:28.091: E/WindowManager(1011): android.view.WindowLeaked: Activity com.dzo.dispatchcrude.driverapp.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{4178fcb0 V.E..... R.....ID 0,0-479,96} that was originally added here
10-23 03:39:28.091: E/WindowManager(1011): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:345)
10-23 03:39:28.091: E/WindowManager(1011): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:239)
10-23 03:39:28.091: E/WindowManager(1011): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
10-23 03:39:28.091: E/WindowManager(1011): at android.app.Dialog.show(Dialog.java:281)
10-23 03:39:28.091: E/WindowManager(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.onPreExecute(SyncDBTask.java:43)
10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask.execute(AsyncTask.java:534)
10-23 03:39:28.091: E/WindowManager(1011): at com.dzo.dispatchcrude.driverapp.asynctask.LoginAsyncTask.onPostExecute(LoginAsyncTask.java:87)
10-23 03:39:28.091: E/WindowManager(1011): at com.dzo.dispatchcrude.driverapp.asynctask.LoginAsyncTask.onPostExecute(LoginAsyncTask.java:1)
10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask.finish(AsyncTask.java:631)
10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask.access$600(AsyncTask.java:177)
10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
10-23 03:39:28.091: E/WindowManager(1011): at android.os.Handler.dispatchMessage(Handler.java:99)
10-23 03:39:28.091: E/WindowManager(1011): at android.os.Looper.loop(Looper.java:137)
10-23 03:39:28.091: E/WindowManager(1011): at android.app.ActivityThread.main(ActivityThread.java:5103)
10-23 03:39:28.091: E/WindowManager(1011): at java.lang.reflect.Method.invokeNative(Native Method)
10-23 03:39:28.091: E/WindowManager(1011): at java.lang.reflect.Method.invoke(Method.java:525)
10-23 03:39:28.091: E/WindowManager(1011): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
10-23 03:39:28.091: E/WindowManager(1011): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-23 03:39:28.091: E/WindowManager(1011): at dalvik.system.NativeStart.main(Native Method)
10-23 03:44:25.761: I/Process(1011): Sending signal. PID: 1011 SIG: 9
更新1
我再次尝试with this approach它在我的情况下也给了toString()错误,它给了toString()错误。我尝试使用Amit's answer时发生了同样的事情。是否有toString()。
更新2
从while循环中删除了新的String构建器对象的创建,现在我没有使用行分隔符。但是,它没有太大的区别。该应用程序首次运行。但是,如果我尝试连续运行2-3次,则会再次出现同样的问题。
答案 0 :(得分:8)
如果你没有足够的内存来存储你的字符串,你可以:释放一些内存,减少内存消耗,不要将字符串存储在内存中。
在您的情况下,您需要:
选项:
答案 1 :(得分:1)
只需将其添加到清单中的<application />
标记:
android:largeHeap="true"
答案 2 :(得分:0)
试试这个,
private String sendPostRequest(String url, List<NameValuePair> params)
throws Exception {
String ret = null;
BufferedReader bufferedReader = null;
HttpClient httpClient = new DefaultHttpClient();
HttpPost request = new HttpPost(url);
try {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params);
request.setEntity(entity);
HttpResponse response = httpClient.execute(request);
bufferedReader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
String line = "";
while ((line = bufferedReader.readLine()) != null) {
ret =ret +line;
}
bufferedReader.close();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ret;
}