由于 AndroidAsyncHttp 1.4.4 的 JsonHttpResponseHandler 存在死循环的 BUG,1.4.5 版本发布不知道要何时,所以只能临时替换该类来修复这个错误。
Android开源库loopj的android-async-http的 JsonHttpResponseHandler 存在死循环GC_CONCURRENT
package com.ai9475.extend; import com.ai9475.meitian.AppManager; import com.ai9475.meitian.R; import com.loopj.android.http.JsonHttpResponseHandler; import android.app.AlertDialog; import android.content.DialogInterface; import android.util.Log; import org.apache.http.Header; import org.apache.http.HttpStatus; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; import java.io.UnsupportedEncodingException; /** * 复写 AndroidAsyncHttp 1.4.4 开源库的 JsonHttpResponseHandler 类 * 当 1.4.5 released 后失效 * * Created by ZHOUZ on 2014/3/22. */ public class ZJsonHttpResponseHandler extends JsonHttpResponseHandler { private static final String LOG_TAG = "JsonHttpResponseHandler"; /** * Returns when request succeeds * * @param statusCode http response status line * @param headers response headers if any * @param response parsed response if any */ public void onSuccess(int statusCode, Header[] headers, JSONObject response) { } /** * Returns when request succeeds * * @param statusCode http response status line * @param headers response headers if any * @param response parsed response if any */ public void onSuccess(int statusCode, Header[] headers, JSONArray response) { } /** * Returns when request failed * * @param statusCode http response status line * @param headers response headers if any * @param throwable throwable describing the way request failed * @param errorResponse parsed response if any */ public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) { } /** * Returns when request failed * * @param statusCode http response status line * @param headers response headers if any * @param throwable throwable describing the way request failed * @param errorResponse parsed response if any */ public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) { } @Override public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { final AlertDialog.Builder dialog = new AlertDialog.Builder(AppManager.ActivityManager.current()); dialog.setIcon(android.R.drawable.ic_dialog_info); dialog.setTitle(R.string.app_error); dialog.setMessage(responseString); dialog.setNegativeButton(R.string.sure, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); dialog.show(); } @Override public void onSuccess(int statusCode, Header[] headers, String responseString) { } @Override public final void onSuccess(final int statusCode, final Header[] headers, final byte[] responseBytes) { if (statusCode != HttpStatus.SC_NO_CONTENT) { new Thread(new Runnable() { @Override public void run() { try { final Object jsonResponse = parseResponse(responseBytes); postRunnable(new Runnable() { @Override public void run() { if (jsonResponse instanceof JSONObject) { onSuccess(statusCode, headers, (JSONObject) jsonResponse); } else if (jsonResponse instanceof JSONArray) { onSuccess(statusCode, headers, (JSONArray) jsonResponse); } else if (jsonResponse instanceof String) { onFailure(statusCode, headers, (String) jsonResponse, new JSONException("Response cannot be parsed as JSON data")); } else { onFailure(statusCode, headers, new JSONException("Unexpected response type " + jsonResponse.getClass().getName()), (JSONObject) null); } } }); } catch (final JSONException ex) { postRunnable(new Runnable() { @Override public void run() { onFailure(statusCode, headers, ex, (JSONObject) null); } }); } } }).start(); } else { onSuccess(statusCode, headers, new JSONObject()); } } @Override public final void onFailure(final int statusCode, final Header[] headers, final byte[] responseBytes, final Throwable throwable) { if (responseBytes != null) { new Thread(new Runnable() { @Override public void run() { try { final Object jsonResponse = parseResponse(responseBytes); postRunnable(new Runnable() { @Override public void run() { if (jsonResponse instanceof JSONObject) { onFailure(statusCode, headers, throwable, (JSONObject) jsonResponse); } else if (jsonResponse instanceof JSONArray) { onFailure(statusCode, headers, throwable, (JSONArray) jsonResponse); } else if (jsonResponse instanceof String) { onFailure(statusCode, headers, (String) jsonResponse, throwable); } else { onFailure(statusCode, headers, new JSONException("Unexpected response type " + jsonResponse.getClass().getName()), (JSONObject) null); } } }); } catch (final JSONException ex) { postRunnable(new Runnable() { @Override public void run() { onFailure(statusCode, headers, ex, (JSONObject) null); } }); } } }).start(); } else { Log.v(LOG_TAG, "response body is null, calling onFailure(Throwable, JSONObject)"); onFailure(statusCode, headers, throwable, (JSONObject) null); } } /** * Returns Object of type {@link JSONObject}, {@link JSONArray}, String, Boolean, Integer, Long, * Double or {@link JSONObject#NULL}, see {@link org.json.JSONTokener#nextValue()} * * @param responseBody response bytes to be assembled in String and parsed as JSON * @return Object parsedResponse * @throws org.json.JSONException exception if thrown while parsing JSON */ protected Object parseResponse(byte[] responseBody) throws JSONException { if (null == responseBody) return null; Object result = null; //trim the string to prevent start with blank, and test if the string is valid JSON, because the parser don't do this :(. If Json is not valid this will return null String jsonString = getResponseString(responseBody, getCharset()); if (jsonString != null) { jsonString = jsonString.trim(); if (jsonString.startsWith("{") || jsonString.startsWith("[")) { result = new JSONTokener(jsonString).nextValue(); } } if (result == null) { result = jsonString; } return result; } /** * Attempts to encode response bytes as string of set encoding * * @param charset charset to create string with * @param stringBytes response bytes * @return String of set encoding or null */ public static String getResponseString(byte[] stringBytes, String charset) { try { return stringBytes == null ? null : new String(stringBytes, charset); } catch (UnsupportedEncodingException e) { Log.e(LOG_TAG, "Encoding response into string failed", e); return null; } } }
现在如果再出现 HTTP 500 或其他服务端错误(输出非 JSON 字符串)时将会直接弹出服务端页面内容的对话框方便调试了,现在只能这样了,等新版本发布后再转换下吧!