How to cancel AsyncTask in Fragment - android

I have created an Android Application, in that I want to cancel AsyncTask onPause state of Fragment.
I tried using AsyncTask.cancel(true); but it gives null pointer exception.
#Override
public void onPause()
{
super.onPause();
AsyncTask.cancel(true);
}
Thanks.

task.cancel() will do it. Be sure to include frequent checks to isCancelled() in your onBackground() as well as in onPostExecute() to avoid accessing/updating UI which is no longer there.
public void onActivityPause() {
task.cancel();
}

asyncTask.cancel(true); will change a boolean value only and don't stop your thread.
so you need to "ask" if the async task not cancelled.
example:
#Override
protected Void doInBackground(Void... params) {
while(!isCancelled()){
// do something
}
return null;
}

Related

Stopping and wrapping 2 sub AsyncTask in android

I need to call task() function from doInBackground() of AsyncTask class. The task function contains 2 sub-async task. So the task() return immediately from doInBackground().
Is it possible to stop(or mark this task done) this task from anywhere else?
How to wrap two sub async task in one.
You don't need to call another AsyncTask from within doInBackground. As a matter of fact, once you get to a high enough API, you'll get an exception. You can call another long running method from within AsyncTask without needing to worry about a thread; you're already in a background thread. If you really feed the need, call another service, but there is no reason to do this.
To stop an AsyncTask, just override OnCancelled. Then you can just call:
task.cancel(true).
EDIT:
If you want to wait for another process to finish before you move on, you can wait for that process to finish by setting a global variable in your class or application and then doing a Thread sleep until done. You will not get an ANR because you are already in a background thread and not on the Main UI:
private boolean processIsDone = false.
//then in your method you are calling from AsyncTask:
private void myLongRunningMethod() {
//do your work here....
//at the end set
processIsDone = true;
}
//in your AsyncTask:
protected Void doInBackground(Void... params) {
//do first part of AsyncTask here
myLongRunningMethod();
do {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (!processIsDone);
//finish the process here.
return null;
}
I do not understand the question exactly but maybe this can help. Use this class in your Activity like this:
myTask = new BackgroundAsyncTask().execute();
And cancel this way:
myTask.cancel(true);
This is the code of the class:
private class BackgroundAsyncTask extends AsyncTask<Object , Object ,String> {
protected void onPreExecute(){
// Do Before execute the main task
}
protected String doInBackground(Object... param) {
//Execute the main task and return for example and String
return res;
}
protected void onPostExecute(String result) {
// You can use the String returned by the method doInBackground and process it
}
}
Hope it's help
About your first question, you can catch event when your task is cancelled by onCancelled() method. try like this:
private CancelTask extends AsyncTask {
private boolean cancelled = false;
protected void onCancelled() {
cancelled = true;
}
protected Object doInBackground(Object... obj) {
do {
// do something...
}while(!cancelled)
}
}
and call AsyncTask.cancel(true); when you want to stop.
CancelTask task = new CancelTask();
task.execute();
...
task.cancel(true);
And about second question, I want to know how you handle two "Sub-AsyncTask"s.
I will try to find a solution after you update your code.

How to really cancel Async task?

I have progressDialog, which is used for my AsyncTask, while downloading file. In AsyncTask I have implemented theese methods:
#Override
protected void onCancelled() {
handleOnCancelled(this.result);
super.onCancelled();
}
#Override
protected void onCancelled(String result) {
super.onCancelled(result);
}
In my activty, I am declaring mProgressDialog and giving it onCancelListener:
mProgressDialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
xml.cancel(true);
}
});
When I press back key, mProgressDialog is closed, onCancel (method above) is called, but Async Task still runs on the background. How to solve it?
Thanks
You need to repeatedly check the boolean isCanceled() within your doInBackground() method. If this method returns true, you should immediately exit any loop or background work being done by the task.
Refer to the docs.
Check for isCanceled() in the async task while you are downloading.
Try This
if(myAsyncTask.getStatus().equals(AsyncTask.Status.RUNNING))
{
myAsyncTask.cancel(true);
}

Android AsyncTask - why is doInBackground() not executed?

I have a nested fragment containing the following method:
public void onSave() {
if (getActivity() == null || view == null) return;
if (file != null && file.exists()) {
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
Log.d("log", "onPreExecute of save ex");
}
#Override
protected Void doInBackground(Void... params) {
Log.d("log", "doInBackground of save ex");
//DO SOMETHING
return null;
}
protected void onPostExecute(Void result) {
BaseFragment fragment = new LocalListFragment();
((LocalLauncherFragment)(LocalEditFragment.this.getParentFragment())).setFragment(fragment);
Log.d("log", "end of save ex");
};
}.execute();
} else {
showAlert();
}
}
My problem is that if I call this method for the first time, it executes until onPostExecute(). However if I go to other fragment and opens this fragment newly(by creating a new fragment object and replacing to it) then only onPreExecute() is executed. Why doesn't this asyncTask object get executed well for the second time?
Intestingly if I use executeOnExecutor() then it works fine for the second time. But why doesn't execute() work? Is AsyncTask's life tied to fragment or something?
Thanks in advance!
It sounds to me like something is hanging in the AsyncTask. In modern versions of Android AsyncTasks run on a single thread unless you specify an Executor that's multi-threaded. onPreExecute() still runs successfully because that runs on the main thread. You never see doInBackground the second time though because the single background thread is still hung from the first call. You'll need to examine the contents of LocalKeekLauncherFragment.setFragment(fragment) to see what's causing the hang.
It seems that doInBackground thread has probably crashed second time.It cannot remain stuck from first try as onPostExecute get called and this is only possible if doInBackground has returned value successfully.

AsyncTask.onCancelled() not being called after cancel(true)

Android SDK v15 running on a 2.3.6 device.
I'm having an issue where onPostExecute() is still being called when I am calling cancel() within a doInBackground() call.
Here is my code:
#Override
public String doInBackground(String... params) {
try {
return someMethod();
} catch (Exception e) {
cancel(true);
}
return null;
}
public String someMethod() throws Exception {
...
}
I am forcing someMethod() to throw an exception to test this out, and instead of onCancelled being called, I always return to onPostExecute(). If I check isCancelled() the returned value is true, so I know that cancel(true) is being executed.
Any ideas?
According to the Android API document, onCancelled() is there since API level 3, while onCancelled(Object result) had been added only since API level 11. Because of that, if the platform API level is below 11, onCancelled() will be invoked always while onCancelled(Object) will be invoked always otherwise.
So, if you want to run your code on all API level 3 and above, you need to implement both methods. In order to have the same behavior you may want to store the result in an instance variable so that isCancelled() can be used as shown below:
public class MyTask extends AsyncTask<String, String, Boolean> {
private Boolean result;
// . . .
#Override
protected void onCancelled() {
handleOnCancelled(this.result);
}
#Override
protected void onCancelled(Boolean result) {
handleOnCancelled(result);
}
//Both the functions will call this function
private void handleOnCancelled(Boolean result) {
// actual code here
}
}
By the way, Eric's code does not likely work because the Android API doc says:
Calling the cancel() method will result in onCancelled(Object) being invoked on the UI thread after doInBackground(Object[])
returns. Calling the cancel() method guarantees that
onPostExecute(Object) is never invoked.
onCancelled is only supported since Android API level 11 (Honeycomb 3.0.x). This means, on an Android 2.3.6 device, it will not be called.
Your best bet is to have this in onPostExecute:
protected void onPostExecute(...) {
if (isCancelled() && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
onCancelled();
} else {
// Your normal onPostExecute code
}
}
If you want to avoid the version check, you can instead do:
protected void onPostExecute(...) {
if (isCancelled()) {
customCancelMethod();
} else {
// Your normal onPostExecute code
}
}
protected void onCancelled() {
customCancelMethod();
}
protected void customCancelMethod() {
// Your cancel code
}
Hope that helps! :)

How to cancel AsyncTask when Activity finishes?

In my Activity I use multiple AsyncTask classes.
How to cancel AsyncTask when Activity finishes?
i think the best place to do this is onStop
protected void onStop() {
super.onStop();
/*
* The device may have been rotated and the activity is going to be destroyed
* you always should be prepared to cancel your AsnycTasks before the Activity
* which created them is going to be destroyed.
* And dont rely on mayInteruptIfRunning
*/
if (this.loaderTask != null) {
this.loaderTask.cancel(false);
}
}
in my Task i then check as often as possible if cancel was called
protected String doInBackground(String... arg0) {
if (this.isCancelled()) {
return null;
}
}
and of course dont forget to drop data that maybe returned since there's no more Activity to receive it
protected void onPostExecute(List<UserStatus> result) {
if(!this.isCancelled()) {
//pass data to receiver
}
}
I don't understand if your "cancel" means rollback but you have a cancel method on the AsyncTask class.
The asynctask thread is kept alive in a thread pool for future istances of AsyncTask. You can't remove them.

Categories

Resources