onCancelled() doesn't get called by calling cancel() once onPostExecute() get called? - android

I am trying to dismiss dialog on onCancelled(Boolean aBoolean) of AsyncTask :
1. It will get called if I call 'myAsyncTask.cancel(true)' if AsyncTask is running.
2. It won't get called if AsyncTask already called onPostExecute().
Do anyone has idea?

Actually, AsyncTask.cancel() doesn’t kill the Thread with no regard for the consequences. All it does is set the AsyncTask to a “cancelled” state. It’s up to the developer of AsyncTask to adhere cancel state.
One of the strategies is to check isCancelled() from time to time and act appropriately. onPostExecute you can also read “cancelled” state and call onCancelled() (or any other function with common logic) manually.

In short, You can't not.
When you called .cancel(true) methods, AsyncTask execute onCancelled instead of onPostExecute.
onPostExecute means Background Tasks is over, back to UI Thread.
I think there is new way.
In onPostExecute, just adding boolean isProcessing = true;
when you don't process onPostExecute, just switch isProcessing's value to false. (I'm not sure about that way)
#Override
protected void onPostExecute(Long result) {
if (isProcessing) {
Log.d(TAG, "onPostExecute - " + result);
}
}

Related

purpose of using onProgressUpdate() in AsyncTask

why should we use onProgressUpdate() method in Asynctask class,
i am using onPreExecute() and onPostExecute() along with doInBackground() but never used onProgressUpdate,In which cases we will use this method.
Thanks in Advance for your response.
onProgressUpdate(Progress...), invoked on the UI thread after a call
to publishProgress(Progress...). The timing of the execution is
undefined. This method is used to display any form of progress in the
user interface while the background computation is still executing.
For instance, it can be used to animate a progress bar or show logs in
a text field.
As you read, you can publish your async task progress by using this.
protected void onProgressUpdate(Integer... progress) {
showProgressPercent(progress[0]);//write your own codes
}
Source
onProgressUpdate() is used to better the user experience by updating the user about the background process initiated at some time. For more information, refer to the docs.
AsyncTask lifecycle : onPreExecute -> doInBackground -> onPostExecute
onPreExecute is calling on MainThread. which means you can touch views.
doInBackground is calling on BackgroundThread. which means you can't touch views.
onPostExecute is calling on MainThread.
so while your job is going on inside doInBackground, you may want to notify user about job's progress but you can't notify user because it's calling on BackgroundThread. you need to jump to MainThread and AsyncTask provides you onProgressUpdate function to make it.
you can call publishProgress inside doInBackground.

AsyncTask status after cancel()?

The documentation for AsyncTask's cancel() method states:
Calling this method guarantees that onPostExecute(Object) is never invoked.
The documentation for AsyncTask.Status.FINISHED states:
Indicates that onPostExecute(Result) has finished.
Does this mean that cancelled AsyncTasks have a status of RUNNING? How can I tell a running task from a cancelled task, in that case?
Based on the source code to AsyncTask, when the background work is done, either onCancelled() or onPostExecute() will be called. After that, the status is set to FINISHED. Prior to that, the task is presumably RUNNING.
You can also call isCancelled() to see if the task was cancelled, before it gets to the FINISHED state.
CommonsWare answer is absolutely correct!
Just wanted to add the specific code snippet from AsyncTask to prove his correctness:
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}

Android - Simple AsyncTask

Hi I have a question about Android AsyncTask.
I have a fragment within an Activity.
That fragment calls AsyncTask where it does something heavy and update the UI in the onPostExecute().
My question is this. LEt's say the user opened the Activity.
Now the fragment is attached and AsyncTask's doInBackground() is called.
Then the user suddenly presses back button to close the activity.
Now, what happens to the execution in the AsyncTask thread?
Does thread also die as soon as the activity is closed?
Or do I have manually check in onPostExecute whether this Fragment is still attached by using isAdded() at the beginning of onostExecute()?
Thanks!
EDIT
In my Fragment, I declare AsyncTask() implicitly.. like this
new AsyncTask<String, Void, Boolean>() {
#Override
protected Boolean doInBackground(String... params) {
return processPlays(plays);
}
#Override
protected void onPostExecute(Boolean result) {
if (!isAdded()) return; // IS THIS FINE?
// UPDATE UI
}
}.execute();
Threads run until they either finish or until Android system dumps the memory. Your AsyncTask will keep running, so you need to do the check if you can't outright cancel it. Else you'll get these situations where your app will crash without you even seeing it open.
Likewise, Fragments can be detached and destroyed during the lifecycle of an app. You can never assume that a Fragment or Activity is still active once returned from an AsyncTask's doInBackground()
On that case the AsyncTask thread will keep running until the end, and if unchecked may crash inside onPostExecute(). Most of the times you'll want to cancel the AsyncTask on the onStop(), onFinish() or even onPause() of the Activity (depending on your application).
You can cancel a Task with the cancel(boolean mayInterruptIfRunning) method. From the Android reference:
A task can be cancelled at any time by invoking cancel(boolean).
Invoking this method will cause subsequent calls to isCancelled() to
return true. After invoking this method, onCancelled(Object), instead
of onPostExecute(Object) will be invoked after
doInBackground(Object[]) returns. To ensure that a task is cancelled
as quickly as possible, you should always check the return value of
isCancelled() periodically from doInBackground(Object[]), if possible
(inside a loop for instance.)

Waiting till the async task finish its work

I'm very new to programming and I have some doubts.
I have a AsyncTask which is I call as RunInBackGround.
and I start this process like:
new RunInBackGround().execute();
But I wish to wait until this call is finish its executing, before proceeding to the other statements of code.
How can I do that?
Are there any way for it?
wait until this call is finish its executing
You will need to call AsyncTask.get() method for getting result back and make wait until doInBackground execution is not complete. but this will freeze Main UI thread if you not call get method inside a Thread.
To get result back in UI Thread start AsyncTask as :
String str_result= new RunInBackGround().execute().get();
Although optimally it would be nice if your code can run parallel, it can be the case you're simply using a thread so you do not block the UI thread, even if your app's usage flow will have to wait for it.
You've got pretty much 2 options here;
You can execute the code you want waiting, in the AsyncTask itself. If it has to do with updating the UI(thread), you can use the onPostExecute method. This gets called automatically when your background work is done.
If you for some reason are forced to do it in the Activity/Fragment/Whatever, you can also just make yourself a custom listener, which you broadcast from your AsyncTask. By using this, you can have a callback method in your Activity/Fragment/Whatever which only gets called when you want it: aka when your AsyncTask is done with whatever you had to wait for.
In your AsyncTask add one ProgressDialog like:
private final ProgressDialog dialog = new ProgressDialog(YourActivity.this);
you can setMessage in onPreExecute() method like:
this.dialog.setMessage("Processing...");
this.dialog.show();
and in your onPostExecute(Void result) method dismiss your ProgressDialog.
AsyncTask have four methods..
onPreExecute -- for doing something before calling background task in Async
doInBackground -- operation/Task to do in Background
onProgressUpdate -- it is for progress Update
onPostExecute -- this method calls after asyncTask return from doInBackground.
you can call your work on onPostExecute() it calls after returning from doInBackground()
onPostExecute is what you need to Implement.
I think the easiest way is to create an interface to get the data from onpostexecute and run the Ui from interface :
Create an Interface :
public interface AsyncResponse {
void processFinish(String output);
}
Then in asynctask
#Override
protected void onPostExecute(String data) {
delegate.processFinish(data);
}
Then in yout main activity
#Override
public void processFinish(String data) {
// do things
}

Android problems with out-of-order multithreaded processing and dialogs

I seem to have consistent problems with timing threads and dialog windows. I've tried using a thread, or onCreate/onPrepare, or an AsyncTask to do some downloading/processing in the background. More often than not, when the background processing completes and dismisses the dialog window, control seems to return to the root thread (Activity/UI thread?) before the dialog is gone or the onPostExecute-like process is done. This makes me think I'm doing it incorrectly. Here is a typical structure (pseudo-code):
public class X {
protected String result = null;
protected ProgressDialog progressDialog;
public void onCreate() {
...
new XTask().execute();
progressDialog.show();
// result is null here, should be "hi"?
// do things with result, like barf on a NPE...sigh
}
private class XTask extends AsyncTask {
protected doInBackground() {
// Get URL.
// Look at contents, takes a few seconds.
// Return the result (should get sent to onPostExecute).
}
protected onPostExecute(r) {
result = r;
progressDialog.dismiss();
}
}
}
I would think that, after doPostExecute sets result and dismisses the dialog, processing then continues in the onCreate method. However, result is often (not always) null at this point in onCreate. Is there a better way to do this? Is this just due to the general crappiness of the emulator?
Thanks.
Edit: To be more concrete, my task (in doInBackground) fetches a URL and does a little processing on the response. This process takes 1-3 seconds. Then, theoretically, onPostExecute sets X.result to what was fetched. I know the URL content is valid and the response is good (not null). The problem is that during those 1-3 seconds, control returns to onCreate, as if the progressDialog never lived at all (it doesn't get displayed in the emulator at all, but that's normal I guess).
I had thought that calling dialog.show() was a blocking method, i.e., the dialog appeared and that method wouldn't continue until it disappeared, but that doesn't seem to be the case. Either my progressDialog.dismiss() is getting called before it should, before setting X.result, or not getting called at all, or dismiss() is happening faster/before the assignment, or something else entirely is going wrong...
Changing the order of the execute and progressDialog doesn't help, nor does moving it into onPreExecute(). Strangely, onPostExecute doesn't get called until I return in onCreate. If I have a Thread.sleep loop after execute (I thought giving it time would help), it never finishes the task until that loop finishes and I return. e.g.:
new XTask().execute();
int z=0;
while (response == null && z < 50) {
Thread.sleep(500);
z++;
}
if (response == null) return;
The task's onPostExecute method doesn't get called until "return". Hmmm...maybe being in onCreate is affecting it.
A ProgressDialog is usually used to block user interaction during loading or heavy processing but the main UI thread will continue to execute.
If you wish to perform some operation on the result you must do it in either onPostExecute of XTask or after you have gotten the result in doInBackground.
private class XTask extends AsyncTask {
#Override
protected void onProgressUpdate(/*params*/){
//modify UI
}
protected doInBackground() {
// Get URL.
// Look at contents, takes a few seconds.
//Option A: Now have the result, do some other processing here
//Cant modify UI components from here, If you need to modify a UI component from
//here call publishProgress() and modify the component in onProgressUpdate()
// Return the result (should get sent to onPostExecute).
}
protected onPostExecute(r) {
result = r;
//Option B do some processing on the result
//You can modify UI components from here
progressDialog.dismiss();
}
}
I would show the progress dialog before triggering the AsyncTask. Normally, when an AsyncTask gets executed, it takes a while to finish itself and in that time, the rest of the task calling method has already run. But in your case the task returns instantly which is probably why the dialog shows up AFTER the postexecute gets called under the AsyncTask.
I would think that, after doPostExecute sets result and dismisses the dialog, processing then continues in the onCreate method.
This is not true, when you call new XTask().execute() in UI thread, application create a worker thread and start running whatever you defied in AsyncTask.doInBackground() on this work thread, at this point (after calling new XTask().execute()), UI thread continue execute code after new XTask().execute().
The point you are talking about where your work thread finish and return to UI thread is AysncTask.onPostExecute(), this method is guaranteed to be called on UI thread after AsyncTask finish. this is the reason why it is called AsyncTask. Both of UI thread and work thread are running asynchronously.
If you want to make your UI thread blocked and wait for AsyncTask finish after XTask().execute(), you can to this:
XTask xTask = new XTask();
xTask.execute();
progressDialog.show();
xTask.get() // <-- this will make your UI thread blocked and wait for AsycnTask at this point
// result is null here, should be "hi"?
This is possible but not a good practice, as AsyncTask.get() will block execution on calling thread so probably get ANR exception.
To sum up
1. AysncTask.onPostExecute() is where process return from worker thread to UI thread, we don't care where and when it will be called on UI thread, we just need ensure it will be called on UI thread properly at some point in the future.
2. AsyncTask.get() by calling this method actually make you AsyncTask running synchronously with the calling thread.
Putting code into the task's onPostExecute should work, a simple test suggests it will (for me). However, I ended up writing a different solution which also works. I put most of the code into a Handler on the activity, which separates it from the UI thread entirely. My onCreate simply shows the loading ProgressDialog window and that's it--it just sits there, "loading". The background task does its thing and when finished, sends a message to the handler. This message tells the handler to dismiss the loading dialog and populate the list. If there are errors, different messages are sent and the handler shows an error dialog.

Categories

Resources