如何在android中处理大量数据

时间:2014-05-12 04:22:20

标签: android mysql

我正在构建一个使用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;
        }

3 个答案:

答案 0 :(得分:2)

我之前见过这个。您的JSON响应太大而无法放入字符串中。有两种可能的解决方案:

1)减少您的请求。这是我在使用大型JSON-RPC响应遇到此问题时选择的路由。在我的情况下,这很简单,因为我正在从具有连续ID的数据存储区加载记录。我需要做的就是请求n记录id > x,然后继续发出相同的请求,直到服务器没有返回任何数据。

2)使用流式JSON解析器,例如JacksonJsonReader。如果你不能实现上述(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/