From eae48b8d9a62bbadad87f1d9a7eefca982be7edb Mon Sep 17 00:00:00 2001 From: Eugene Pogrebnoy Date: Fri, 28 Mar 2014 15:52:27 +0200 Subject: [PATCH 1/2] Fixed AsyncHttpResponseHandler to properly work on threads without Looper --- .../loopj/android/http/AsyncHttpClient.java | 4 +++ .../http/AsyncHttpResponseHandler.java | 25 ++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/library/src/main/java/com/loopj/android/http/AsyncHttpClient.java b/library/src/main/java/com/loopj/android/http/AsyncHttpClient.java index 16c0b682c..77334fc7d 100644 --- a/library/src/main/java/com/loopj/android/http/AsyncHttpClient.java +++ b/library/src/main/java/com/loopj/android/http/AsyncHttpClient.java @@ -978,6 +978,10 @@ public RequestHandle delete(Context context, String url, Header[] headers, Reque * @return RequestHandle of future request process */ protected RequestHandle sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) { + if (responseHandler != null && responseHandler.getUseSynchronousMode()) { + throw new IllegalArgumentException("Synchronous ResponseHandler used in AsyncHttpClient. You should create your response handler in a looper thread or use SyncHttpClient instead."); + } + if (contentType != null) { uriRequest.setHeader("Content-Type", contentType); } diff --git a/library/src/main/java/com/loopj/android/http/AsyncHttpResponseHandler.java b/library/src/main/java/com/loopj/android/http/AsyncHttpResponseHandler.java index b59001a9f..5c24e3809 100644 --- a/library/src/main/java/com/loopj/android/http/AsyncHttpResponseHandler.java +++ b/library/src/main/java/com/loopj/android/http/AsyncHttpResponseHandler.java @@ -163,8 +163,16 @@ public String getCharset() { * Creates a new AsyncHttpResponseHandler */ public AsyncHttpResponseHandler() { - // There is always a handler ready for delivering messages. - handler = new ResponderHandler(this); + boolean missingLooper = null == Looper.myLooper(); + // Try to create handler + if (!missingLooper) + handler = new ResponderHandler(this); + else { + // There is no Looper on this thread so synchronous mode should be used. + handler = null; + setUseSynchronousMode(true); + Log.i(LOG_TAG, "Current thread has not called Looper.prepare(). Forcing synchronous mode."); + } // Init Looper by calling postRunnable without an argument. postRunnable(null); @@ -319,14 +327,13 @@ protected void sendMessage(Message msg) { * @param runnable runnable instance, can be null */ protected void postRunnable(Runnable runnable) { - boolean missingLooper = null == Looper.myLooper(); if (runnable != null) { - if (missingLooper) { - // If there is no looper, run on provided handler - handler.post(runnable); + if (getUseSynchronousMode()){ + // This response handler is synchronous, run on current thread + runnable.run(); } else { - // Otherwise, run on current thread - runnable.run(); + // Otherwise, run on provided handler + handler.post(runnable); } } } @@ -339,7 +346,7 @@ protected void postRunnable(Runnable runnable) { * @return Message instance, should not be null */ protected Message obtainMessage(int responseMessageId, Object responseMessageData) { - return handler.obtainMessage(responseMessageId, responseMessageData); + return Message.obtain(handler, responseMessageId, responseMessageData); } @Override From 3ac8d50f8c277f558230466373b42748db0bc72e Mon Sep 17 00:00:00 2001 From: Eugene Pogrebnoy Date: Fri, 28 Mar 2014 18:47:55 +0200 Subject: [PATCH 2/2] Fixed threading issues in BaseJsonHttpResponseHandler and JsonHttpResponseHandler --- .../http/BaseJsonHttpResponseHandler.java | 16 ++++++++++++---- .../android/http/JsonHttpResponseHandler.java | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/library/src/main/java/com/loopj/android/http/BaseJsonHttpResponseHandler.java b/library/src/main/java/com/loopj/android/http/BaseJsonHttpResponseHandler.java index 5aed5e4ef..bc5deabd0 100644 --- a/library/src/main/java/com/loopj/android/http/BaseJsonHttpResponseHandler.java +++ b/library/src/main/java/com/loopj/android/http/BaseJsonHttpResponseHandler.java @@ -74,7 +74,7 @@ public BaseJsonHttpResponseHandler(String encoding) { @Override public final void onSuccess(final int statusCode, final Header[] headers, final String responseString) { if (statusCode != HttpStatus.SC_NO_CONTENT) { - new Thread(new Runnable() { + Runnable parser = new Runnable() { @Override public void run() { try { @@ -95,7 +95,11 @@ public void run() { }); } } - }).start(); + }; + if (!getUseSynchronousMode()) + new Thread(parser).start(); + else // In synchronous mode everything should be run on one thread + parser.run(); } else { onSuccess(statusCode, headers, null, null); } @@ -104,7 +108,7 @@ public void run() { @Override public final void onFailure(final int statusCode, final Header[] headers, final String responseString, final Throwable throwable) { if (responseString != null) { - new Thread(new Runnable() { + Runnable parser = new Runnable() { @Override public void run() { try { @@ -125,7 +129,11 @@ public void run() { }); } } - }).start(); + }; + if (!getUseSynchronousMode()) + new Thread(parser).start(); + else // In synchronous mode everything should be run on one thread + parser.run(); } else { onFailure(statusCode, headers, throwable, null, null); } diff --git a/library/src/main/java/com/loopj/android/http/JsonHttpResponseHandler.java b/library/src/main/java/com/loopj/android/http/JsonHttpResponseHandler.java index 227f41cdc..63648a15a 100644 --- a/library/src/main/java/com/loopj/android/http/JsonHttpResponseHandler.java +++ b/library/src/main/java/com/loopj/android/http/JsonHttpResponseHandler.java @@ -113,7 +113,7 @@ 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() { + Runnable parser = new Runnable() { @Override public void run() { try { @@ -142,7 +142,11 @@ public void run() { }); } } - }).start(); + }; + if (!getUseSynchronousMode()) + new Thread(parser).start(); + else // In synchronous mode everything should be run on one thread + parser.run(); } else { onSuccess(statusCode, headers, new JSONObject()); } @@ -151,7 +155,7 @@ public void run() { @Override public final void onFailure(final int statusCode, final Header[] headers, final byte[] responseBytes, final Throwable throwable) { if (responseBytes != null) { - new Thread(new Runnable() { + Runnable parser = new Runnable() { @Override public void run() { try { @@ -181,7 +185,11 @@ public void run() { } } - }).start(); + }; + if (!getUseSynchronousMode()) + new Thread(parser).start(); + else // In synchronous mode everything should be run on one thread + parser.run(); } else { Log.v(LOG_TAG, "response body is null, calling onFailure(Throwable, JSONObject)"); onFailure(statusCode, headers, throwable, (JSONObject) null);