How to kill a AsyncTack thread properly in Android? - android

I subclass an AsyncTask in my Android project.
I want to implement a feature that allow user to cancel the current AsyncTack and start a new one if the current task take too much time.
MyAsyncTask mat = new MyAsyncTask();
When the user click the cancel button, I will implement the following code and then start a new task.
mat.cancel(true);
However, I realize later that the new task doesn't start until the old task is finish. The old task tread is still executing.
I check the official document on google. It seems that I should call the following statement in doInBackGroud(Params... params).
if (isCancelled()) break;
The problem is I found that the code below is responsible for taking long time.
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
But how can I check whether the task is cancelled or not while httpClient.execute(httpPost) is executing?
Is there some method like onProgressChanged(int progress) that I can override in DefaultHttpClient?

I want to implement a feature that allow user to cancel the current
AsyncTack and start a new one if the current task take too much time.
Since you cannot start a new task until the old task is finish, you can create a new instance of the Asyntask. In fact, its a bad idea to use a instance of AsyncTask multiple times.
After your
HttpResponse httpResponse = httpClient.execute(httpPost);
You can check if it was canceled
if(!isCanceled()){
}
Look in the docs, last line under Threading Rules.
Update
as comment pointed out. Depends on your platform , so check the platform version before execute.
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else {
myTask.execute();
}

You need to abort your request by calling abort on your httpPost object. This will cause the execute method to return immediately and to stop blocking your thread.

I would actually avoid using AsyncTask altogether. AsyncTasks are prone to memory leaks and are poorly tied to the Activity lifecycle so you'll end up getting yourself into trouble.
Consider using RoboSpice as not only it will help you solve your question, but it'll avoid the problems with AsyncTasks and skip having to write stuff manually with HttpClient. I am not one of the devs for RoboSpice, but I've started using it recently and it's an excellent project.

Related

Xamarin Android correct Asynchronous way

i am new on xamarin android apps.I want to build an app and i have read that connections with database or the execution of queries should happen asynchronously from the main thread otherwise the UIthread will may collapse.I have found 2 ways to do that:
First way:
WebClient client = new WebClient();
Uri uri = new Uri("http://192.168.2.8/CreateUsername.php");
NameValueCollection parameters = new NameValueCollection();
parameters.Add("Name", txtname.text);
client.UploadValuesCompleted += Client_UploadValuesCompleted;
client.UploadValuesAsync(uri,parameters); ---> is this gonna create a new thread and run asynchronously???
(here i found the first way: https://www.youtube.com/watch?v=jF3D__ibrx8 )
SecondWay:
https://developer.xamarin.com/recipes/android/web_services/consuming_services/call_a_rest_web_service/
Both ways are correct?both of ways are gonna create a new thread and run asynchronously?Thanks!!!!
Both examples are ok but I'd usually trust the official documentation by Xamarin first. What might confuse you with the first example is the lack of await keyword when calling the UploadValuesAsync method. Here's what actually happens:
Call to UploadValuesAsync is made from the UI thread.
UI thread blocks until the method returns because it's running synchronously.
However, the method returns very quickly because it launches the upload process asynchronously on another thread internally and doesn't wait for the process to complete.
When the whole upload process is finished, Client_UploadValuesCompleted will be called.
As you can see on the WebClient.UploadValuesAsync page on MSDN, it states that:
These methods do not block the calling thread.
Also, when looking at the source code for UploadValuesAsync, you'll notice the following attribute defined on top:
[HostProtection(ExternalThreading=true)]
which means the following:
Code that exposes external threading creates or manipulates threads other than its own, which might be harmful to the host.
To sum it up, the upload process is handled on another background thread but otherwise, your code will run synchronously. There's a bit more asynchronicity going on in Xamarin's sample.

What is the relationship between AsyncTask and Activity? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I have been given an assignment to develop an application that send server request and get response and then using JSON parsing, display the data content into a ListView.
I don't understand about AsyncTask and how to integrate all classes. Hope you will accommodate.
regards
What should you do?
The first, send a request to server
The second, get response
The thirds, Parse data from InputStream which you got from Response
The fourth, show on ListView
Oh, done.
Right now,
Look into the first step.
How to send a request to server?
You can use HttpURLConnection or HttpClient
So, What's problem when you send a request to server?
I think you know when you send a request to server, you will get some problem: Network bad, InputStream from Server too large, ...
And how to resolve?
With single statement, you can't take along time to do. So with task which will takes along time to do, you have to handle in other thread. That's reason why we should use Thread or AsyncTask.
What's AsyncTask?
You can read more by search on Google. I just tell you: How to use AsyncTask to solve your spec.
What does AsyncTask do?
When you create an instance of AsyncTask,
It's will follow:
-> Create -> PreExecute -> Execute (DoInBackground) - PostExecute
Ok.
Right now, I will answer your question:
Create an object which extends AsyncTask.
public class DownloadFile extends AsyncTask<String, Void, InputStream> {
#Override
public void onPreExecute() {
// You can implement this method if you want to prepare something before start execute (Send request to server)
// Example, you can show Dialog, or something,...
}
#Override
public InputStream doInBackground(String... strings) {
// This is the important method in AsyncTask. You have to implements this method.
// Demo: Using HttpClient
InputStream mInputStream = null;
try {
String uri = strings[0];
HttpClient mClient = new DefaultHttpClient();
HttpGet mGet = new HttpGet(uri);
HttpResponse mResponse = mClient.execute(mGet);
// There are 2 methods: getStatusCode & getContent.
// I dont' remember exactly what are they. You can find in HttpResponse document.
mInputStream = mReponse.getEntity().getContent();
} catch (Exception e) {
Log.e("TAG", "error: " + e.getMessage());
}
return mInputStream;
}
#Override
public void onPostExecute(InputStream result) {
//After doInBackground, this method will be invoked if you implemented.
// You can do anything with the result which you get from Result.
}
}
Ok. Now we have to use this class
In your MainActivity or where you want to invoke this class, create an instance of this class
DownloadFile mDownloader = new DownloadFile();
mDownloader.execute("your_url");
Using method mDownloader.get(); to get InputStream if you want to get. But you have to surround by try-catch
I know, if you want to use Dialog, you will search on Google how to show Dialog while download file from server.
And I suggest you that you should remember, you nead runOnUiThread if you want to Update UI.
Because an AsyncTask is Thread. So you can not Update UI if you are in another Thread which is not MainThread.
AsyncTask
AsyncTask enables proper and easy use of the UI thread. It is used when you want to perform long awaited task in background.
It publish result on the UI thread(display result to the UI) without having to manipulate any threads or handlers.It means that user doesn’t bother about Thread management, everything is managed by itself. And thats why it is known as Painless Threading, see below point.
It is also known as Painless Threading.
The result of AsyncTask operation is published on UI thread. It has basically 4 methods to override: onPreExecute, doInBackground, onProgressUpdate and onPostExecute
Never expect to be a programmer by referring short notes, study deep..
Look here for more detail.

What is the best practice for a Multithreading Handler on Android?

I have an app, which uses several HTTPRequests for example
get a session id
get some locationdata
get existing categories
(...) and some more
I created a HTTPRequestHandler, which basically manages all the AsynTasks for each Request... This works well, but my problem is, I don't know a good way for managing the different AsynTasks. For example, you need to get the SessionId Task before you can start the GetSomeLocationData Task
So in my HTTPRequestHandler I have a queue, which starts the depending AsyncTasks like:
private void startSessionIdTask(...) {
//...
GetSessionIdTask mGetSessionIdTask = new GetSessionIdTask(this);
mGetSessionIdTask.execute(url);
}
//and from the postExecute() in GetSessionIdTask I call
public void setSessionId(int mSessionId) {
mDataHelper.setmSessionId(mSessionId); //set id
String url = API_URL + API_GET_FAVORITES + URL_VARIABLE;
List<NameValuePair> params = new LinkedList<NameValuePair>();
params.add(new BasicNameValuePair("session_id", getSessionId()));
String paramString = URLEncodedUtils.format(params, "utf-8");
url += paramString;
//and finally start another Tasks (and so one...)
GetLocationsTask mGetLocationsTask = new GetLocationsTask(this);
mGetSessionIdTask.execute(url);
}
However, this works fine, but the problem is, that (depending on the connection), this queue takes time, and the user can start other AsynTasks which fail, because some initially data is not loaded yet.
I could set some Boolean like isSessionIdLoaded or could block the UI for the user, but I'm wondering, if there s any better solution?!
So my question is: Is there a way to put asyntasks in some kind of queue (ArrayList, Map..) which will be executed in a row?
As of Android 3+ AsyncTasks will be executed in serial on the AsyncTask.SERIAL_EXECUTOR. So by default if you start 2 AsyncTasks
task1.execute();
task2.execute();
Task2 will only be executed if task1 has finished (just check the sdk implementaion of AsyncTask.SERIAL_EXECUTOR). This can be pushed to that point, that if task1 for any reason never finishes, task2 will never start and you have deadlocked your app.
If you want your own queue independed from the default SERIAL_EXECUTOR, just use
public final AsyncTask<Params, Progress, Result> executeOnExecutor (Executor exec, Params... params)
And provide your own executor (aka threadpool). For one project I copyed the SERIAL_EXECUTOR implementation to have 2 serial queues.
For Android 2.3 to 1.6 all tasks are by default in parallel, similiar to calling in Android 3+:
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,null);
Unfortunatly in Android 2.3 und lower you have no option of specifing the executor on which the task/thread will be run on. So if you want to have it done serially, you have to implement it yourself, by calling task2 only after task1 has finished explicitly in onPostExecute(). This concept can of course be pushed to use a queue of task where the former task will call the next one when it's finished (= serial worker queue). For this you will find plenty literature and patterns.
I'm not entirely sure what you're asking, but if you'd just like a way to queue up Runnables to execute in a background thread in sequence, then Executors.newSingleThreadExecutor() may be what you're looking for. It's more complicated than it probably needs to be, but you can find examples and tutorials easily enough via google.
If you need sequential execution, I'd recommend switching to IntentService instead of using AsyncTask. See docs: http://developer.android.com/reference/android/app/IntentService.html

How to extract HttpResponse into a separate thread?

I have in Android:
HttpResponse httpGetResponse = client.execute(request);
...
Log.e("HEADER: ", httpGetResponse.getStatusLine().toString() );
i.e. I execute a HttpGet request and then do something with the response. Yet I want to somehow place it into a separate thread, so that the UI thread won't freeze while the server responds. What do you think would be the best way to do that?
Thansk!
Wrap your request into an AsyncTask and do the actual request in the doInBackground. As you probably have to use the output on the UI thread you probably should return the data you need from within the doInBackground and use the postExecute option in AsyncTask.
The simplest way is to use an AsyncTask.

How to cancel DefaulHttpClient execution process in multithread

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 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.
The RestClient object your using doesn't expose any interrupt() method of DefaultHttpClient (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 an AsyncTask. This won't solve the problem of you're client.Execute() from blocking but will allow you to throw away the listener (replacing it with onProgressUpdate() or onPostExecute()).
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 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 of RestClient though - since your RestClient does not expose the underlying DefaultHttpClient object (from which you can get to the ClientConnectionManager using the getClientConnectionManager() method).
Use the threading primitives. Have a flag running and set it to true initially. Do your REST requests in a while(running) loop.
In your onPause(), set the running flag to false.

Categories

Resources