Skip to content

Commit c3a3e6c

Browse files
author
Alex Boyd
committed
adding Looper to AsyncHttpHandler constructor to allow constructing them on background threads
1 parent 89cd47e commit c3a3e6c

File tree

5 files changed

+170
-4
lines changed

5 files changed

+170
-4
lines changed

library/src/main/java/com/loopj/android/http/AsyncHttpResponseHandler.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ public abstract class AsyncHttpResponseHandler implements ResponseHandlerInterfa
9898

9999
private URI requestURI = null;
100100
private Header[] requestHeaders = null;
101+
private Looper looper = null;
101102

102103
@Override
103104
public URI getRequestURI() {
@@ -125,7 +126,8 @@ public void setRequestHeaders(Header[] requestHeaders) {
125126
private static class ResponderHandler extends Handler {
126127
private final AsyncHttpResponseHandler mResponder;
127128

128-
ResponderHandler(AsyncHttpResponseHandler mResponder) {
129+
ResponderHandler(AsyncHttpResponseHandler mResponder, Looper looper) {
130+
super(looper);
129131
this.mResponder = mResponder;
130132
}
131133

@@ -143,15 +145,15 @@ public boolean getUseSynchronousMode() {
143145
@Override
144146
public void setUseSynchronousMode(boolean value) {
145147
// A looper must be prepared before setting asynchronous mode.
146-
if (!value && Looper.myLooper() == null) {
148+
if (!value && this.looper == null) {
147149
value = true;
148150
Log.w(LOG_TAG, "Current thread has not called Looper.prepare(). Forcing synchronous mode.");
149151
}
150152

151153
// If using asynchronous mode.
152154
if (!value && handler == null) {
153155
// Create a handler on current thread to submit tasks
154-
handler = new ResponderHandler(this);
156+
handler = new ResponderHandler(this, this.looper);
155157
} else if (value && handler != null) {
156158
// TODO: Consider adding a flag to remove all queued messages.
157159
handler = null;
@@ -178,6 +180,14 @@ public String getCharset() {
178180
* Creates a new AsyncHttpResponseHandler
179181
*/
180182
public AsyncHttpResponseHandler() {
183+
this(null);
184+
}
185+
186+
/**
187+
* Creates a new AsyncHttpResponseHandler
188+
*/
189+
public AsyncHttpResponseHandler(Looper looper) {
190+
this.looper = looper == null ? Looper.myLooper() : looper;
181191
// Use asynchronous mode by default.
182192
setUseSynchronousMode(false);
183193
}

sample/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
<activity android:name=".RetryRequestSample"/>
4040
<activity android:name=".RangeResponseSample"/>
4141
<activity android:name=".Http401AuthSample"/>
42+
<activity android:name=".AsyncBackgroundThreadSample"/>
4243

4344
<service android:name=".services.ExampleIntentService"/>
4445
</application>
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
Android Asynchronous Http Client Sample
3+
Copyright (c) 2014 Marek Sebera <[email protected]>
4+
http://loopj.com
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package com.loopj.android.http.sample;
20+
21+
import android.app.Activity;
22+
import android.os.Looper;
23+
import android.util.Log;
24+
import android.widget.Toast;
25+
26+
import com.loopj.android.http.AsyncHttpClient;
27+
import com.loopj.android.http.AsyncHttpResponseHandler;
28+
import com.loopj.android.http.RequestHandle;
29+
import com.loopj.android.http.ResponseHandlerInterface;
30+
31+
import org.apache.http.Header;
32+
import org.apache.http.HttpEntity;
33+
34+
import java.util.concurrent.Callable;
35+
import java.util.concurrent.ExecutorService;
36+
import java.util.concurrent.Executors;
37+
import java.util.concurrent.FutureTask;
38+
import java.util.concurrent.TimeUnit;
39+
40+
public class AsyncBackgroundThreadSample extends SampleParentActivity {
41+
private static final String LOG_TAG = "AsyncBackgroundThreadSample";
42+
43+
private ExecutorService executor = Executors.newSingleThreadExecutor();
44+
45+
@Override
46+
public void onStop()
47+
{
48+
super.onStop();
49+
}
50+
51+
@Override
52+
public RequestHandle executeSample(final AsyncHttpClient client, final String URL, final Header[] headers, HttpEntity entity, final ResponseHandlerInterface responseHandler) {
53+
54+
final Activity ctx = this;
55+
FutureTask<RequestHandle> future = new FutureTask<>(new Callable<RequestHandle>() {
56+
public RequestHandle call() {
57+
Log.d(LOG_TAG, "Executing GET request on background thread");
58+
return client.get(null, URL, headers, null, responseHandler);
59+
}
60+
});
61+
62+
executor.execute(future);
63+
64+
RequestHandle handle = null;
65+
try {
66+
handle = future.get(5, TimeUnit.SECONDS);
67+
Log.d(LOG_TAG, "Background thread for GET request has finished");
68+
} catch (Exception e) {
69+
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
70+
e.printStackTrace();
71+
}
72+
73+
return handle;
74+
}
75+
76+
@Override
77+
public int getSampleTitle() {
78+
return R.string.title_async_background_thread;
79+
}
80+
81+
@Override
82+
public boolean isRequestBodyAllowed() {
83+
return false;
84+
}
85+
86+
@Override
87+
public boolean isRequestHeadersAllowed() {
88+
return false;
89+
}
90+
91+
@Override
92+
public String getDefaultURL() {
93+
return "https://httpbin.org/get";
94+
}
95+
96+
@Override
97+
public ResponseHandlerInterface getResponseHandler() {
98+
99+
FutureTask<ResponseHandlerInterface> future = new FutureTask<>(new Callable<ResponseHandlerInterface>() {
100+
101+
@Override
102+
public ResponseHandlerInterface call() throws Exception {
103+
Log.d(LOG_TAG, "Creating AsyncHttpResponseHandler on background thread");
104+
return new AsyncHttpResponseHandler(Looper.getMainLooper()) {
105+
106+
@Override
107+
public void onStart() {
108+
clearOutputs();
109+
}
110+
111+
@Override
112+
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
113+
Log.d(LOG_TAG, String.format("onSuccess executing on main thread : %B", Looper.myLooper() == Looper.getMainLooper()));
114+
debugHeaders(LOG_TAG, headers);
115+
debugStatusCode(LOG_TAG, statusCode);
116+
debugResponse(LOG_TAG, new String(response));
117+
}
118+
119+
@Override
120+
public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
121+
Log.d(LOG_TAG, String.format("onFailure executing on main thread : %B", Looper.myLooper() == Looper.getMainLooper()));
122+
debugHeaders(LOG_TAG, headers);
123+
debugStatusCode(LOG_TAG, statusCode);
124+
debugThrowable(LOG_TAG, e);
125+
if (errorResponse != null) {
126+
debugResponse(LOG_TAG, new String(errorResponse));
127+
}
128+
}
129+
130+
@Override
131+
public void onRetry(int retryNo) {
132+
Toast.makeText(AsyncBackgroundThreadSample.this,
133+
String.format("Request is retried, retry no. %d", retryNo),
134+
Toast.LENGTH_SHORT)
135+
.show();
136+
}
137+
};
138+
}
139+
});
140+
141+
executor.execute(future);
142+
143+
ResponseHandlerInterface responseHandler = null;
144+
try {
145+
responseHandler = future.get();
146+
Log.d(LOG_TAG, "Background thread for AsyncHttpResponseHandler has finished");
147+
} catch (Exception e) {
148+
e.printStackTrace();
149+
}
150+
151+
return responseHandler;
152+
}
153+
}

sample/src/main/java/com/loopj/android/http/sample/WaypointsActivity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ public class WaypointsActivity extends ListActivity {
5252
new SampleConfig(R.string.title_custom_ca, CustomCASample.class),
5353
new SampleConfig(R.string.title_retry_handler, RetryRequestSample.class),
5454
new SampleConfig(R.string.title_range_sample, RangeResponseSample.class),
55-
new SampleConfig(R.string.title_401_unauth, Http401AuthSample.class)
55+
new SampleConfig(R.string.title_401_unauth, Http401AuthSample.class),
56+
new SampleConfig(R.string.title_async_background_thread, AsyncBackgroundThreadSample.class)
5657
};
5758

5859
@Override

sample/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@
3535
<string name="title_retry_handler">Retrying requests by Exception</string>
3636
<string name="title_range_sample">Range response handling</string>
3737
<string name="title_401_unauth">401 basic authentication</string>
38+
<string name="title_async_background_thread">Async on background thread</string>
3839
</resources>

0 commit comments

Comments
 (0)