AsynchTask got onPostExecute() method tied to UI thread. Assume that we close an activity by pressing back button while AsynchTask doInBackground() method is still in progress.
I want to know will onPostExecute executes by considering that activity is not displaying on screen anymore?
In case answer is yest, will it cause exceptions or not? (because of accessing UI objects which are not longer displayed on screen).
1-I want to know will onPostExecute executes by considering that
activity is not displaying on screen anymore?
yes!
2-In case answer is yest, will it cause exceptions or not? (because of
accessing UI objects which are not longer displayed on screen).
Yes! it may cause Exception because your Instance of your Activity and Views which you use in your AsyncTask are not exist anymore
This Link will help you more : AsyncTask won't stop even when the activity has destroyed
Related
Could anyone explain what does exactly happens (lifecycle of Asynctask) if for example I have and Activity with a Fragment and from this Fragment I execute an Asynctask where on the onPreExecute I start displaying a ProgressDialog and at some point I close the app while the Asynctask is still running?
As far as I've checked the Fragment doesn't call onDetach nor onDestroy and the Asynctask doesn't reach the onPostExecute method or onCancelled
If i am not wrong you are familiar with lifecycle of an AsyncTask. If not, refer
https://developer.android.com/reference/android/os/AsyncTask.html
To answer why onPostExecute method is not called when we exit the app while the progress bar is still running, I would say it is because, AT holds a reference to the Activity/Context which would be destroyed by the time progress bar decides it's job is done(bg task/thread).
Very useful blog on how to handle ATs wrt fragments and activities by Alex Lockwood.
http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
Have you set setRetainInstance(true) in your fragment, whenever you start asynctask inside a fragment with setRetainInstance as true the task will continue to run in background without interrupt which is not in the case of an activity
Please ensure that AsyncTask.doInBackground() has been completed. Or, what is more possible, your main thread is stuck somewhere as AsyncTask.onPostExecute() must be executed in main thread.
In the scenario you are speaking about, the Fragment methods "onPause()" and "onStop()" will be called (besides of the ones of the Activity which contains the given Fragment).
As those methods are being called, you should react according to what you want to do in the AsyncTask.
If that's not the case, refer to the link given by #stack_ved.
Anyway, if you want to do any kind of load inside a Fragment, I strongly recommend you to use "Loaders" or "AsyncTaskLoader".
https://developer.android.com/reference/android/content/AsyncTaskLoader.html
I have read that an AsyncTask keeps running even if the calling activity has stopped. Keeping this in mind, I am trying to understand the working of onTaskCompleted. onTaskCompleted is usually called from onPostExecute() of the AsyncTask and if the calling activity still exists, everything is good. But what if the calling activity has stopped? Will this result in a crash of the app?
This question came to me because I was thinking of updating some global variables or UI components in the calling activity on the result of the AsyncTask. Is this a good idea? Won't this also result in a crash?
Thanks.
in my activity, i have an asynctask that downloads a series of images...(it may take some time depending on the size of the images)... before i execute the asynctask, i display a progress dialog in onPreExecute and a notification (when user clicks on notification it is redirected to my activity with the progress dialog). when my asynctask completes, in onPostExecute, i remove the dialog and the notification.. i handle screen orientation by using onRetainNonConfigurationInstanceto save my asynctask so that when screen is rotated, i check if task is still running and i display the progress dialog if it is still running in onCreate
Problem : sometimes: my asynctask downloads only 1 file and it seems that it gets killed...(no exception in logcat)... as a result, my notication is always there and my progress dialog also... and they remain there indefinitely....
i have tried the solution by Jeff Axelrod there: How can I ensure an AsyncTask is completed before my activity is killed?:
It looks like if I override the onPause() event in my activity, and from within the overridden onPause(), I call cancel(false) on the AsyncTasks, then the activity is not destroyed until the AsyncTasks are completed.
seems to do the trick but problem is that my onPostExecute is not called anymore; all images download fine but as onPostExecute is not executed, notification and progress dialog still remain there forever.
waiting for your solutions guys! i read use asyntask only for short task; will the use of thread and handler solves my problem? will android kills my activity or thread if the latter is not finished??
Best way how to handle Asynctask is described in this article.
In short, the idea is to keep AsyncTask in fragment with setRetainInstance(true); these will keep You AsyncTask alive all time user is in activity holding this fragment and won't be destroyed on configuration change (orientation change).
If You need Your AsyncTask to run after user leaves Activity, for example goes to next Activity but You wish download to continue You should use services.
I know it sounds crazy that someone is using runOnUiThread inside AsyncTask. Somehow, it is working for me but I wanna know if it is an acceptable and robust approach or not. Here is the scenario:
I have an app in which after successful login, user is rendered to next screen. In this new screen, 3 different methods are loading different types of data from a web server. These methods are:
getMembersForList() : It loads the list of community members and shows it in a listview.
getProfileData() : It loads the profile of logged in user and shows his name , image etc on the screen.
getNotificationCounts : It loads the count of new notifications for the user.
I applied 3 different approaches for it :
(1) Calling all 3 methods simply in onCreate i.e. no exclusive thread is being used for any of the methods . In this case , the transition from login screen to this screen becomes very slow and black screen shows up for some time before this activity shows up.
(2) Calling getMembersForList() on UI thread and the other 2 methods on exclusive threads. In this case transition becomes fast and list shows up quickly but Notification counts and username etc. don't show up because WrongThreadException occurs saying that this thread can't touch other thread's views (TextViews for username, notification count etc. which are declared globally) . The same thing happens when I start these threads from an AsyncTask as well.
(3) Calling getMembersForList() on UI thread and then starting an AsyncTask in which the other 2 methods are being called in "runOnUiThread" inside doInBackground() method. This solves both the above issues. Now the screen transition is faster and the WrongThread exception is also not occuring.
So far the approach-(3) is working good for me but I am not sure if this is the right way to do it because runOnUiThread and AsyncTask are 2 completely opposite things. Can anyone please clear my doubts about this scenario. Thanx in advance.
Yes, use-cases like this are a big reason why the runOnUiThread() method exists in the first place. The idea is you allow your background thread(s)/AsyncTask instance(s) to run your lengthy operations in the background, and then provide a simple hook that they can use to update the interface when they have the result (or at arbitrary intervals, as different pieces of the result become available).
As long as that's what you're doing, then your usage is fine. What you want to avoid doing is performing a lengthy operation on the main thread, either directly or indirectly by passing in some lengthy operation from a background thread.
Of course you don't have to do it that way if you don't want to. You could use postExecute() instead. Or you could store the result somewhere and then use any sort of message-passing API to notify the main thread that the result is ready, and so on.
I would advice to run all the 3 calls in the asyncTask, and update the UI in the postExecute() of the AsyncTask after the background taks is complete, postExecute runs on UIthread so you need not call anything explicit to run them on UIthread.
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.