在执行后台操作时出现内存不足的错误

3
我有以下代码: -
public class ByState extends Fragment {
    @Nullable
    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.by_state, container, false);
        new GetAllStates().execute("dummy");
        return rootView;
    }
}
class GetAllStates extends AsyncTask<String,String,String> {
    @Override
    protected String doInBackground(String... key) {
        StringBuffer response = new StringBuffer();
        try {
            String url = "http://congress-search-148802.appspot.com/getData.php?value=legislator";
            URL obj = new URL(url);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();
            con.setRequestMethod("GET");
            int responseCode = con.getResponseCode();
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }

            in.close();
        } catch (Exception e) {
            Log.w("Error", e.getMessage());
        }
        return response.toString();
    }
    @Override
    protected void onPostExecute(String groupResponse) {
        Log.d("My message",groupResponse);
        try {
            JSONArray groupList = new JSONArray(groupResponse);
            for(int i=0;i<groupList.length();i++){
                JSONObject groupInfo = groupList.getJSONObject(i);

                Log.d("BioguideID ",groupInfo.getString("bioguide_id"));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

我并没有做太多的事情,但仍然出现了以下错误:
1-15 00:05:02.793 27120-27157/com.app.congress.congressapp E/art: Throwing OutOfMemoryError "Failed to allocate a 203542 byte allocation with 150292 free bytes and 146KB until OOM"
11-15 00:05:02.803 27120-27157/com.app.congress.congressapp E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
    Process: com.app.congress.congressapp, PID: 27120
    java.lang.RuntimeException: An error occured while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:304)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
        at java.util.concurrent.FutureTask.run(FutureTask.java:242)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)
    Caused by: java.lang.OutOfMemoryError: Failed to allocate a 203542 byte allocation with 150292 free bytes and 146KB until OOM
        at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
        at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:125)
        at java.lang.StringBuilder.append(StringBuilder.java:271)
        at java.io.BufferedReader.readLine(BufferedReader.java:414)
        at com.app.congress.congressapp.GetAllStates.doInBackground(ByState.java:46)
        at com.app.congress.congressapp.GetAllStates.doInBackground(ByState.java:34)
        at android.os.AsyncTask$2.call(AsyncTask.java:292)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
        at java.lang.Thread.run(Thread.java:818

我尝试将堆大小增加到大堆,尽管这并不被推荐,但仍然遇到了此错误。作为一个相对新手,有人能指出我哪里做错了吗?


你是在使用设备还是模拟器(AVD)? - zerocool
1
你需要处理完整的响应吗?难道你不能使用文件吗? - AxelH
我目前正在使用AVD。 - Zxxxxx
是的,我需要完整的响应在列表视图中显示。 - Zxxxxx
StringBuffer引起错误。这是一个昂贵的任务。尝试寻找替代方案。 - Vygintas B
请尽量在真实设备上进行测试,如果您的文件非常大,请将其分块处理。 - zerocool
3个回答

4

很简单,您正在尝试缓冲过多的数据。

这是罪魁祸首:

while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}

由于您的数据源为JSON,您可以简单地使用 JsonReader 逐个解析数据源。这样,您可以在不将所有数据同时存储在内存中的情况下读取所有数据。
官方文档中有使用 JsonReader的示例
在您的情况下,您需要这样初始化:
JsonReader reader = new JsonReader(new InputStreamReader(con.getInputStream()));

1

使用大堆栈是不好的解决方案。相反,使用Gson StreamingJackson。您也可以使用@knossos的答案。


0

将解析Json的代码也放入doInBackground()方法中


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接