Is it necessary to stop manually timed tasks (with Handler) when the activity stops / view is detached / etc. Or will the system just remove them?
I have, for example, a Runnable which I use to update a TextView each second. When the user leaves the activity, do I have to call removeCallbacks(task)?
I tried both (remove and not) and they work, but I don't know if the timer keeps running unnecessarily or this can lead to exceptions under certain circumstances.
Thanks in advance.
yes it has to be handled or cancelled., while you are using the Timer Task it should be cancelled before the respective task or activity or app closes., otherwise it will process its content even after the instance closed too....
Related
I've read
"How to know activity has been finished?
" and "Proper way to know whether an Activity has been destroyed"
but none of them got real answers
I've a background task updating a screen with it's progress
The user has a button to cancel the background task at any moment, and if he does that the background task will be stoped and activity will be finished...
BUT as all of this happen in an asynchronous enviroment the following situation may happen:
1- the background task stacks some notification to update progress activity
2- the user cancel the background task
3- the background task is stopped (i mean, stops having progress) and activity is finished (activity.finish())
4- the previous stacked updates are delivered to the activity which tries to perform some update on its fields and lead to error
I would like an "oficial android approach" better than having a boolean which is set to true during onDestroy()
Since you're finishing the activity by calling finish() then I think checking isFinishing() before updating the UI would work in your use case.
For more advanced use cases I suggest you should look into RxJava for doing asynchronous background tasks that are tightly coupled with activity lifecycle.
I am writing an Android app (ICS) for a tablet. The user moves from Activity A to Activity B to Activity C with the touch of a button. I want to return from Activity C to Activity A after 10 seconds. Is there some way to count to 10 without locking up Activity C?
I've succeeded with an asyncTask but if I startActivity(A) in the onPostExecute() it feels like I'm violating the guideline that an asyncTask should not mess with the UI. I've tried get() but that does lock up Activity C while it's waiting for the 10 seconds to pass.
Thanks in advance!
Assuming you have any View instance in your activity, you can use View.postDelayed() to post runnable with a given delay. In this runnable you can call Activity.finish(). You should also use View.removeCallbacks() to remove your callback in onDestroy(), to avoid your callback being called after user already navigated back from your activity.
Using AsyncTask just to count some time is just an overkill (unless you want to use AsyncTask to actually do some useful, background work). The Looper and Handler classes provide everything you need to execute any code on UI thread after a given delay. The View methods mentioned above are just convenience methods exposing the Handler functionality.
Using AsyncTask works fine as you describe. From Android Documentation:
onPostExecute(Result), invoked on the UI thread after the background computation finishes.
Since it is invoked on UI thread you should be fine.
Documentation
You can use a alarm manager for that. Set it to send a broadcast 10 seconds starting from activity a and implement a base activity for activity a b and c to receive the broadcast, after receiving the broadcast just end the current activity and start activity a with a new flag. If the current instance is activity a then ignore if not start activity a. Something like that.
As for the idle part you can update the alarm manager on every action, upon entering activity etc.
The advantage of this implementation is that you dont have to go through the hassle of having to worry about context leaks, persisting timers across activities and such. and can make use of what is already there. You can also consider using a service though.
If not you can just use the shared preference store the time to time out and check or update against it for the actions.. A simpler implementation.
Good luck.
If I have an AsyncTask started in an Activity by user interaction. The AsyncTask, when finished, will modify the UI and execute a Toast. Let's say that the user exits the Activity before the AsyncTask has finished. Can this cause problems as in Exceptions: I.e. could it happen that an UI element pointer goes null and that when the AsyncTask finishes it could cause runtime exceptions?
As it is now I've done a design where the Application class handles the AsyncTask and notifies the Activity through a BroadcastReceiver to do UI tasks if Activity still is around (i.e. more of an Observer pattern). Is this a "safer" design?
/ Henrik
I believe this does cause a problem. If the activity that created the AsyncTask is not around anymore, the an exception is thrown because the parent handler is not there anymore. The correct approach is to keep the reference of the AsyncTask in that activity, and capture onPause() event. In the pause event, I would cancel the AsyncTask and clean up if there is anything that needs to be cleaned up.
To answer your second question, it all depends on what is the requirement. If the requirement is for that task to still be around then yes you can attach the AsyncTask to the application. But it sounds like there is something that might be not correct here. You said if Activity still is around. If you don't need the task once the activity has disappeared then you might as well go with my original approach which is cancel the task and throw it away when the activity is paused.
Also, one final note. If you keep a reference to the activity around even after the activity has stopped, you will have a memory leak because that activity still has a reference that cannot be cleaned up until the task has completed.
This article sounds similar to what you are doing. If you really want to keep the task around then this seems like a good solution. I also found Android AsyncTask Context Terminated that might help you.
I'm going nuts here.
I want a simple thing - I have a long task (fetching several data objects from the web) and I want the ability to cancel it.
I tried a lot of things (a lot) and nothing works
The flow goes like this:
the user click on a button
I start the work (I tried with AsyncTask, Service, IntentService and Looper)
the task takes care of everything including adding ongoing notification for progress updates
the intent in the notification has a call for a new activity that her only purpose is to cancel the ongoing task
in the cancelActivity I tried to call stopService() for Service/IntentService or do
Looper.quit() for the Looper (I don't remember what I tried for AsyncTask, not sure if there is such api for canceling it)
In my point of view the best option will be using IntentService (I could have several task lining up and IntetService will do it in order like I want) but
I'm open to suggestions for any type of implementation - I don't care what the code will be, just that I will have the option to cancel the task
Thank you in advance for your help
Dror
(I'm off to bed - 8 hours on the same issue is just too much)
It does not matter what specific operation you use to stop the task if you don't recognize the stop condition in your background logic. The only way to cleanly accomplish it is if background worker stops and exits in good faith.
There are few possible scenarios and solutions that you can use for canceling background work.
Background thread executes many short steps (for example computation with some loops). In this case, check some flag (could be isInterrupted()) between operations and exit if this flag indicates that operation must stop.
Background thread is waiting on monitor. Call interrupt() on background thread, catch exception in in exception handler make appropriate steps to finish this task cleanly and exit.
Background thread is waiting on IO. This use case is very hard to solve in general case. If you use some socket, you can try closing this socket externally and catch the exception. In worst case scenario, you can just abandon the thread in the state that if it ever returns from IO it knows that it is canceled and IO results must be discarded. If you do it often - you will run out of memory, so I would not really recommend it.
In any case, there is no way (except killing the thread which is really bad) to stop your task if it does not know about possibility of being stopped.
Ok, i manged to do something close to what I want.
I'm using IntentService that will queue my task. each new task is AsyncTask. the AsyncTask starts with sending notification with pendingIntent for cancelActivity.
When clicking on the notification the user gets a warning popup about stopping the task. If he clicks yes than I do stopService() on my IntentService.
In the IntentService I added:
#Override
public void onDestroy() {
currentTask.cancel(true);
if (mNotificationHelper != null)
mNotificationHelper.completed();
super.onDestroy();
stopSelf();
}
in the AsyncTask I added:
#Override
protected void onCancelled() {
isCanclled = true;
httpClient.getConnectionManager().shutdown();
mNotificationHelper.completed();
if (mAsyncTaskListener != null)
mAsyncTaskListener.AsyncTaskCanceled();
}
so that will drop all the connection currently in motion. In the actual code that do the work I need to catch the exception for connection shutdown and handle it
so in the end I'm not actually stopping the AsyncTask/Service but rather exposing the httpClient so I will be able to drop the connection in asynchrony why.
I think is a bit ugly but I got no other way
thank you all
I have a main game thread but when the target score is achieved I have an activity that is launched called StageCleared which basically displays the stats to the user of their performance and then they can press a continue button to carry on with the game. This should switch focus back to the running thread that should continue execution, and thus display the game activity (with parameters i update after StageCleared has exectued).
It was suggested I use a package visible object that calls wait() on itself in the main game thread, and then notify() on itself from StageCleared in order to continue execution. My first problem is I can't seem to declare a package visible object that can be seen by all the classes in my package? Secondly, is this the best way to achieve what I'm intending to do or is there a better way?
Many thanks
To enable package visibile, leave the modifier blank:
static boolean mVarname = true;
mVarname is visible inside the package.
I work with a run flag to enable if the loop should do something or just "idle". I, too, dont know if this is a good way to do it :)
Use FutureTask and Executor, check it out in Java API.
It's like, you define the operation and FutureTask, and it'll wait until the task is completed.
Easier than wait()