I am developing an android application that rely very much on internet, I retrieve data frequently using this RestClient Class, that wrap some detail on using DefaultHttpClient to do network request.
And I always use different thread to do the HTTP request, I create a class like this:
public class AsyncWorker {
final String SERVER_URL = "http://api.blabla.com";
RestClient client = new RestClient();
public void requestHttp(final String url, final ArrayList<NameValuePair> params, final RequestListener listener) {
new Thread(new Runnable() {
public void run() {
try {
client.setUrl(url);
client.setParams(params);
client.Execute(RestClient.RequestMethod.POST);
String response = client.getResponse();
listener.onComplete(response);
} catch (Exception ex) {
Log.d("LOGIN", ex.getMessage());
}
}
}).start();
}
etc...
So whenever I need to do a HTTP request, I only need to create AsyncWorker
object, and provide the RequestListener
callback interface.
But the problem is, how can I cancel the HTTP Request when the user press the back/cancel button? and in this case the application still is in one activity, for example I create a dialog, and the user do a request from that dialog, and then back button pressed, the dialog dismissed, and I need to cancel the request on that time.
I suggest you take a look at the
ClientConnectionManager
interface. This allows you to do stuff like releasing a connection, shutting down a connection etc. You may need to enhance the implementation ofRestClient
though - since yourRestClient
does not expose the underlyingDefaultHttpClient
object (from which you can get to theClientConnectionManager
using thegetClientConnectionManager()
method).Use the threading primitives. Have a flag
running
and set it totrue
initially. Do your REST requests in awhile(running)
loop.In your
onPause()
, set the running flag tofalse
.The
RestClient
object your using doesn't expose anyinterrupt()
method ofDefaultHttpClient
(which is the backing object doing most of the work). Not a problem - the DefaultHttpClient doesn't seem to have any interrupt or abort functionality to expose in the first place.So, your left with a blocking operation on
client.Execute()
.Your half way to having a solution - which is to put the blocking operation into a Thread. Where your falling down is your architecture - your using a Thread/Listener setup which doesn't give you alot of wiggle room.
Try switching your anonymous
Thread
to anAsyncTask
. This won't solve the problem of you'reclient.Execute()
from blocking but will allow you to throw away the listener (replacing it withonProgressUpdate()
oronPostExecute()
).What this will do is allow you call
task.cancel()
, signalling to the Task it is no longer needed. This will allow you to reassign a new AsyncTask, orphaning the cancelled task, the orphaned thread will then finish quickly as its able and die quietly while the rest of your application gets on with what it needs to.((On an unrelated note, "Execute()" is a method and shouldn't be capitalised))
I had the same issue and was able to find a fix. Here is what I did:
I used CloseableHttpClient along with other related classes, instead of the DefaultHttpClient that by default comes with Android.
These classes are from https://hc.apache.org/downloads.cgi. OR for direcet access: http://apache.mirrors.hoobly.com//httpcomponents/httpclient/binary/httpcomponents-client-4.3.2-bin.tar.gz
With this, calling the abort() method on the Request object will actually halt the connection. However, using this library is not the solution; reason being that Android already has the outdated HTTPCLIENT library inbuilt, and most classes in the library pointed to by the above link would appear to be missing at runtime.
The problem is that both the packages in the above library and the inbuilt org.apache httpclient package have same namespace, and would result in the use of only the inbuilt org.apache classes provided by Android at compilation.
An example of this issue is found here: java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE.
Thanks to the guys who provided http://code.google.com/p/httpclientandroidlib/ as an option (found in the answer section of java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE)
Recommendation: one place to actually cancel an http request could be within OnCancel Listener of a progress dialog, instead of the AyncTask's onCancelled() callback method.