我正在构建一个使用json从mysql服务器获取数据的应用程序。我实现了延迟加载来处理内存不足错误。有一段时间,应用程序运行得很好但现在我再次得到内存不足错误。这次只针对数据,而不针对图像。有没有办法处理数据,同时保持应用程序响应? logcat输出如下 -
05-12 09:42:50.271: E/AndroidRuntime(1093): FATAL EXCEPTION: AsyncTask #2
05-12 09:42:50.271: E/AndroidRuntime(1093): Process: com.opaxlabs.salepurchase, PID: 1093
05-12 09:42:50.271: E/AndroidRuntime(1093): java.lang.RuntimeException: An error occured while executing doInBackground()
05-12 09:42:50.271: E/AndroidRuntime(1093): at android.os.AsyncTask$3.done(AsyncTask.java:300)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.util.concurrent.FutureTask.run(FutureTask.java:242)
05-12 09:42:50.271: E/AndroidRuntime(1093): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.lang.Thread.run(Thread.java:841)
05-12 09:42:50.271: E/AndroidRuntime(1093): Caused by: java.lang.OutOfMemoryError
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:145)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.lang.StringBuffer.append(StringBuffer.java:219)
05-12 09:42:50.271: E/AndroidRuntime(1093): at com.opaxlabs.salepurchase.CustomHttpClient.executeHttpGet(CustomHttpClient.java:150)
05-12 09:42:50.271: E/AndroidRuntime(1093): at com.opaxlabs.salepurchase.AllItemsActivity$AsyncData.doInBackground(AllItemsActivity.java:106)
05-12 09:42:50.271: E/AndroidRuntime(1093): at com.opaxlabs.salepurchase.AllItemsActivity$AsyncData.doInBackground(AllItemsActivity.java:1)
05-12 09:42:50.271: E/AndroidRuntime(1093): at android.os.AsyncTask$2.call(AsyncTask.java:288)
05-12 09:42:50.271: E/AndroidRuntime(1093): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
05-12 09:42:50.271: E/AndroidRuntime(1093): ... 4 more
感谢任何帮助。提前谢谢。
编辑: 发生错误的代码如下 -
protected Item[] doInBackground(String... arg0) {
String str = null;
try {
str = CustomHttpClient.executeHttpGet(arg0[0]);
JSONArray array = new JSONArray(str);
item_data = new Item[array.length()];
selectionId = new int[array.length()];
for (int i = 0; i < item_data.length; i++) {
JSONObject jdata = array.getJSONObject(i);
String path = Constants.THUMBS + jdata.getString("name");
int itemid = jdata.getInt("id");
String cityid = jdata.getString("city_id");
item_data[i] = new Item(itemid, cityid, path,
jdata.getString("title"), jdata.getString("price"));
selectionId[i] = jdata.getInt("subcategory_id");// change
// the
// field
// name
// here
}
} catch (JSONException j) {
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return item_data;
}
答案 0 :(得分:2)
我之前见过这个。您的JSON响应太大而无法放入字符串中。有两种可能的解决方案:
1)减少您的请求。这是我在使用大型JSON-RPC响应遇到此问题时选择的路由。在我的情况下,这很简单,因为我正在从具有连续ID的数据存储区加载记录。我需要做的就是请求n
记录id > x
,然后继续发出相同的请求,直到服务器没有返回任何数据。
2)使用流式JSON解析器,例如Jackson或JsonReader。如果你不能实现上述(1),这是最好的 - 也可能是唯一的 - 解决方案。
答案 1 :(得分:1)
This should be inside doinbackground
try
{
JSONObject json = new JSONObject(str_json);
JSONArray jsonArray = json.getJSONArray("user_list");
if(jsonArray.length()>0)
{
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject jsonObject = jsonArray.getJSONObject(i);
responseContactList.add(jsonObject);
}
adapterContact = new myAdapterContact(ShareEvent.this, responseContactList);
return jsonArray.length();
}
} catch (JSONException e) {
e.printStackTrace();
}
here the responseContactList is a global class level arraylist of jsonobjects
and this should be in postexecute
@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
if(result>0)
{
listViewContact.setAdapter(adapterContact);
}
below is adapter
private class myAdapterContact extends BaseAdapter
{
LayoutInflater inflater;
private ArrayList<JSONObject> data = new ArrayList<JSONObject>();
public myAdapterContact(Activity a, ArrayList<JSONObject> d) {
data=d;
inflater = LayoutInflater.from(a);
}
@Override
public int getCount() {
return data.size();
}
and then in side getview method values should be set as on the textview
holder.contact_name.setText (data.get(position).getString("display_name"));
答案 2 :(得分:0)
在你的情况下,它甚至在解析之前实际上已经没有内存了(参见堆栈跟踪中的StringBuilder引用)。这是更多的工作,但您应该考虑使用JsonReader进行解析,因为它可以获取输入流而无需将内容写入字符串。
请参阅本教程:http://kahdev.wordpress.com/2012/03/11/android-parsing-json-with-jsonreader/