I have two buttons in my UI.Both button actions i am calling the same async class.when i click on the second button,first button execution of the async thread stops forcebly and start the execution again.
How to stop forceble execution of async thread in android?
To cancel an async task, you may need to call the cancel() method on the task object, with parameter true.
Eg:
yourAsynObj.cancel(true);
also, you need to check if the task is cancelled in your doInBackground method, you can check it as
if(!yourAsynObj.isCancelled){
// do things
} else {
// Cancel doing things
}
private YourAsyncTask mTask;
declare your asyncTask in your activity.
mTask = new YourAsyncTask().execute();
instantiate it like this.
mTask.cancel(true);
kill/cancel it like this.
Related
I have a created non activity java class for doing same calculation from different activities. This class has asynctask with progress Dialog in it. In most cases calculation is not the last operation of activity and everything goes fine, but when it is my Progress Dialog goes lost.
Example:
myJavaClass doCalculations= new myJavaClass (SomeActivity.this);
doCalculations.Do(); //<------ method Do has asysctask with Progress Dialog
finish();
result:
java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{2bbf820e V.E..... R......D 0,0-1026,483} not attached to window manager
How can I wait for asynctask to finish and then finish activity?
Additional question: Is using asynctask in non activity class is a bad practice ?
If you want to keep your activity active until the AsyncTask has finished its job, you can define a callback method in the activity that gets called when the task has finished and can react appropriately:
In the Activity:
private boolean finishAfterCurrentTask = false;
public void onTaskFinished() {
if (finishAfterCurrentTask) { // set this to true when running the last task
finish();
}
}
In the AsyncTask:
protected void onPostExecute(Object result) {
progressDialog.dismiss();
activity.onTaskFinished();
}
I'm assuming that you're keeping a reference to the activity in myJavaClass. In case that you're calling the AsyncTask from a non-UI thread, you should probably run the callback (and also all methods involving the dialog) via Activity.runOnUiThread().
As for the second question - if you use an AsyncTask in a class which methods can be called from a thread other than the UI thread, it's necessary to use runOnUiThread() to perform any operations on the UI, such as changing the contents of a view or showing/hiding a dialog, beause onPreExecute() and onPostExecute() are called from the same thread as execute().
On the other hand, if you start the task inside one of the UI callbacks, which are guaranteed to run on the UI thread, you don't need to worry about that.
The AsyncTask has a onPostExecute method you can finish the activity from there
protected void onPostExecute(Long result) {
progressDialog.dismiss();
finish(); // you'll probably have to call finish() with a callback function
}
The onPostExecute method is called when the doInBackground method is finished, on that method you can finish the activity and close the progressdialog
I want to cancel the Async Task on the particular condition.
I am doing the following stuff:
MyService.java
....
if(condition){
asyncTask.cancel(true); // its return the true as well
}
...
MyAsynTask.java
...
protected Object doInBackground(Object... x) {
while (/* condition */) {
// work...
if (isCancelled()){ // Here task goes in to wait state
break;
}
else{
//continue to download file
}
}
return null;
}
...
Using DDMS I found that task goes into wait State. Any suggestion to resolve this issue will be highly appreciated.
Thanks,
Yuvi
AsyncTask is a piece of work for PoolExecutor. When you execute your first task Executor creates first thread and executes your task on it. After task execution is finished the thread is not deleted. It starts waiting for a new task.
So it is normal to see AsyncTask thread in wait state.
P.S. It's better not to use AsyncTask for longtime operation. Use your own executor or thread.
P.P.S. AsyncTask uses single thread executor since 4.x. Be careful )
after you explicitly call asyncTask.cancel(true);, the onCancelled() method is called. Try overriding the following method:
#Override
protected void onCancelled() {
//what you want to do when the task was cancelled.
}
I have a custom progress dialog within an AsyncTask which acts as a download progress, I want to interrupt doInBackground when my custom cancel button pressed. It seems when the dialog dismisses, doInBackground resumes without any problems!
I want to interrupt doInBackground when my custom cancel button pressed.
=> call cancel() method of your AsyncTask inside the cancel button click event. Now this is not enough to cancel doInBackground() process.
For example:
asyncTask.cancel(true);
To notify that you have cancelled AsyncTask using cancel() method, you have to check whether its cancelled or not using isCancelled() inside doInBackground().
For example:
protected Object doInBackground(Object... x)
{
// do your work...
if (isCancelled())
break;
}
You could call AsyncTask.cancel(true) from the cancel event of the dialog. For this you do need a reference to the AsyncTask, this could be an instance variable initialized when the task is started. Then in the asyncTask.doInBackground() method you can check for isCancelled(), or override the onCancelled() method and stop the running task there.
Example:
//Asynctask instance variable
private YourAsyncTask asyncTask;
//Starting the asynctask
public void startAsyncTask(){
asyncTask = new YourAsyncTask();
asyncTask.execute();
}
//Dialog code
loadingDialog = ProgressDialog.show(ThisActivity.this,
"",
"Loading. Please wait...",
false,
true,
new OnCancelListener()
{
#Override
public void onCancel(DialogInterface dialog)
{
if (asyncTask != null)
{
asyncTask.cancel(true);
}
}
});
EDIT: If you create the dialog from inside the AsyncTask, the code would not be very different. You probably wouldn't need the instance variable, I think you could call YourAsyncTask.this.cancel(true) in that situation.
I have a function, AppHelper.isOnline(Context context), I call in various parts of my application to check that a session didn't timeout before making an HTTP request.
public void onClick(View v) {
Intent intent = null;
switch (v.getId()) {
case R.id.buttonPagamenti:
if (AppHelper.isOnline(this))
{
//here AppHelper.isOnline should have finished it's async task
intent = new Intent(this, OrdineCreaActivity.class);
this.startActivityForResult(intent, R.id.buttonPagamenti);
}
break;
...
Inside AppHelper.isOnline(), I am executing an AsyncTask that logs in, thus making a network request, which can't be run on UI because otherwise I get an exception. I need to wait for it to finish BEFORE resuming with the code inside the if. How can I do this ?
Problem is the activity starts firsts, then the AsyncTask executes, so when the activity expects a valid logged in session, it breaks.
You have two options:
Either use the AsyncTask's method get(long timeout, TimeUnit unit) like that:
task.get(1000, TimeUnit.MILLISECONDS);
This will make your main thread wait for the result of the AsyncTask at most 1000 milliseconds (as per #user1028741 comment: actually there is also infinetly waiting method - AsyncTask#get() which might also do the work for you in some cases).
Alternatively you can show a progress dialog in the async task until it finishes. See this thread (No need for me to copy past the code). Basically a progress dialog is shown while the async task runs and is hidden when it finishes.
You have even third option:" if Thread is sufficient for your needs you can just use its join method. However, if the task is taking a long while you will still need to show a progress dialog, otherwise you will get an exception because of the main thread being inactive for too long.
try using
if (AppHelper.isOnline(this))
{
while(!task.isCancelled()){
// waiting until finished protected String[] doInBackground(Void... params)
}
intent = new Intent(this, OrdineCreaActivity.class);
this.startActivityForResult(intent, R.id.buttonPagamenti);
}
For more information read http://developer.android.com/reference/android/os/AsyncTask.html
Rafiq's response did not work for me - the app hung. I think the reason has to do with the nature of isCancelled(): "Returns true if this task was cancelled before it completed normally." If the task completes normally (i.e. is not cancelled) then while(!task.isCancelled()) { } will loop forever.
To solve this create a Boolean flag that you instatiate to false and then flip to true in task.onPostExecute(). Then do while(!flag) { } before switching Activities. Additionally, if you'd like to give the main thread a 'break' to let the AsyncTask process a little faster, you can do try this:
while (!flag) {
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
It seems to be working well for me.
intent = new Intent(this, OrdineCreaActivity.class);
context.startActivityForResult(intent, R.id.buttonPagamenti);
Write the above lines in onPostExecute() of you AysncTask. Because if we are using AsyncTask it wont wait there until the task complete.
I want to stop a AsyncTask thread from another AsyncTask thread. I have tried like
new AsyncTask.cancel(true) to stop the background process but it didn't stop.
Could any one help me on this?
declare your asyncTask in your activity:
private YourAsyncTask mTask;
instantiate it like this:
mTask = new YourAsyncTask().execute();
kill/cancel it like this:
mTask.cancel(true);
The reason why things aren't stopping for you is because the process (doInBackground()) runs until it is finished. Therefore you should check if the thread is cancelled or not before doing stuff:
if(!isCancelled()){
// Do your stuff
}
So basically, if the thread is not cancelled, do it, otherwise skip it :)
Could be useful to check for this some times during your operation, especially before time taking stuff.
Also it could be useful to "clean up" alittle in
onCancelled();
Documentation for AsyncTask:
http://developer.android.com/reference/android/os/AsyncTask.html
Hope this helps!
You may also have to use it in onPause or onDestroy of Activity Life Cycle:
//you may call the cancel() method but if it is not handled in doInBackground() method
if (loginTask != null && loginTask.getStatus() != AsyncTask.Status.FINISHED)
loginTask.cancel(true);
where loginTask is object of your AsyncTask
Thank you.
You can't just kill asynctask immediately. In order it to stop you should first cancel it:
task.cancel(true);
and than in asynctask's doInBackground() method check if it's already cancelled:
isCancelled()
and if it is, stop executing it manually.
I had a similar problem - essentially I was getting a NPE in an async task after the user had destroyed the fragment. After researching the problem on Stack Overflow, I adopted the following solution:
volatile boolean running;
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
running=true;
...
}
public void onDestroy() {
super.onDestroy();
running=false;
...
}
Then, I check "if running" periodically in my async code. I have stress tested this and I am now unable to "break" my activity. This works perfectly and has the advantage of being simpler than some of the solutions I have seen on SO.
u can check onCancelled() once then :
protected Object doInBackground(Object... x) {
while (/* condition */) {
if (isCancelled()) break;
}
return null;
}