Can Activity lifecycle callbacks interrupt each other or happen concurrently? - android

Do Activity lifecycle callbacks like onCreate(), onStart(), onResume(), always wait for the former to finish before executing, or is it possible that onStart() gets called before onCreate() finishes, interrupts it, and then onCreate continues after onStart() finishes. Is it even possible that they run concurrently, like can onStart() get called while onCreate() hasn't finished, and then a line of onStart() executes, and then a line of onCreate(), and so on.
I assume this isn't the case, and logging on my app shows it isn't, but I haven't ever seen it mentioned explicitely, because I can't know what it's like on other versions, or devices. I also read that each app gets one thread by default, so I think that means that it can't be concurrent, but I wanna make sure.
The main thing that got me thinking about this is the fact that some people online say that in an Activity onCreateOptionsMenu() is called after onCreate() starts but before it finishes. For an example the first answer here. But another user said somewhere else that on some versions onCreateOptionsMenu() is called inside setContentView(), and I guess that's why that is. So does it go something like this then?
onCreate() -> onCreateOptionsMenu() called, onCreate() paused -> onCreateOptionsMenu() finishes -> onCreate() is resumed
Did I get this right? There is no concurrency involved?
And something like this can't happen for the main callbacks like onCreate(), onStart(), onResume()?

You are referencing very old questions/answers regarding the timing of onCreateOptionsMenu(), and these very old posts refer to ActionBarSherlock which was a library that was not part of the Android framework (and may not have followed the rule that I describe below).
As far as I know, all calls to framework methods on Activity or Fragment (unless specifically documented as otherwise) are made on the main (UI) thread. This means that they cannot be interrupted by any other framework calls, that they run to completion and that they cannot run in parallel. My own personal empirical analysis agrees.

Related

Activity lifecycle callbacks no fininshing execution?

Is it possible that activity lifecycle callbacks get interrupted before executting all its code? can a callback interrupt another?
https://developer.android.com/guide/components/activities/activity-lifecycle
In this documentation it recommends not implementing heavy work in onPause for example as it has a "very brief execution", who controls that? how? does the system calls the next lifecycle callback even if onPause did not finish execution yet?
Docs suggest that onResume()/onPause() execute rapidly for better user experience, because these methods are called frequently. Android activity callbacks are always executed in a sequence. They may be interrupted only by an uncaught exception which will terminate the whole app.
Those calls are what will influence UI mostly (along with onCreate, onCreateView) and if they take a long time to complete their code the user will most certainly know about it.
Say you have this in your onResume() method
OnResume(){ super.onResume; updateView(); }
Something standard, this is what normally happens before the fragment or activity gets “resumed”.
If your updateView(); required 2seconds to complete, weather it’s loading data or creating objects, that’s 2 seconds that the UI is “frozen” and the user cannot use the app, or could mistake as “is broken”
If you have the theoretical same scenario for onPause() then that too is 2 seconds of “frozen” time in the app
It is preferred to have the “updateView()” (essentially your onResume and onPause methods) complete as quickly as possible so that the user does not notice any “lag” in the application.

What we should do in onStart, OnResume, OnPause

Hi I have gone though activity lifecyle on many threads, but I could not find what we should do in onStart, onResume, onPause method of the activity.
In the onStart() method, you add code that's relevant at the beginning of the activity.
Let's say, you have an app that reads the temperature of the device's battery. You'll want to have an initial value, so as to show the user.
So in the onStart(), you'd add code that goes ahead and fetches the information you'd need, and displays it for the user, before your timer (for example) goes and reads the information a minute later.
The onPause() method is called before the application goes in to the background.
To stay with our example, in the onPause() method, you'd save the last recorded temperature to the device; so you can show a comparison when the user next opens the app.
The onResume() method is called when the application is brought back to the foreground (i.e.: you've gone to the task manager, and tapped on your app to show it again).
Again, staying with the going example; in the onResume() method, you'd go ahead, read your saved data, load fresh data, and show a comparison of the two in the application.
Then, when your timer ticks next, only fresh data will be shown.
Your question is a bit vague, so answer might not be super specific..
I would say there are no strict "rules" around what we should do in corresponding activity lifecycle methods.
In fact, you can do nothing there (just make sure you call super method if you decided to override those). I.e. your custom activity might not even override these methods - it will work just fine.
onStart, onResume and onPause methods are just hints to you about activity lifecycle change, so you can react accordingly, i.e. start/stop specific to your activity operations at the appropriate time.
For instance, when onResume is called it means that activity became fully visible to the user, so you might want to start some animation (if necessary)
Again, you are not obligated to put any code in there.
Usually most of the operations are performed within oncreate and onresume.
However for your info let me brief it out,
Onstart- this is called after Oncreate, once activity is visible to the user, if you want to perform some operations before the visibility do it in Oncreate, because most of codes should be operated before user views the activity.
OnResume-Be cautious on Onresume is it is quite tricky it will be called whenever you activity is brought to foreground.
Onpause-Called before Onresume, codes wont be executed here, so strictly avoid adding codes in Onpause instead add inside Onresume.
Hope it helps,

Activity onStart() not called when resuming an recreated activity from a stack

Long story short: I am currently working on a small android game. One feature is being able to change the app theme. When the user changes the theme, an event is broadcasted throughout the app and all active activities call recreate() to apply the new theme.
The problem:
Let's say there is a stack of activities: A, B, C. All activities will receive the event in the order they were opened and call recreate(). These are the lifecycle events that will get called (in order):
Activity A will call onDestroy(), onCreate(), onStart(), onResume() and onPause()
Activity B will call onDestroy(), onCreate(), onStart(), onResume() and onPause()
Activity C will call onPause(), onStop(), onDestroy(), onCreate(), onStart(), onResume().
Note that neither activity A or B called onStop(). When those activities are being returned to (eg. back button press), they will not call onStart() when they become visible, but will call onResume(). This is contrary to what is stated in the activity lifecycle documentation.
The question: Is there something I'm doing wrong here? Is there another way to restart all activities in an application without messing up the activity lifecycle?
I think you are taking the wrong approach here. You should not use the framework calls in order to change your theme. The issue you are having is that you are not calling onStop as the framework would, but even so...
The primary reason your approach is incorrect is that Android may have already destroyed an Activity if it is not visible. So sending events to it that call framework methods is not only unnecessary at that point, but it could result in unpredictable states and behavior. Could even cause a crash.
For changes to your theme or any UI component, you should handle that in onResume - in other words handle changes to the UI elements when the user returns to the Activity. One option for doing this is passing flags through startActivityForResult.
Better, make your theme selection persist using sharedPreferences (or using another method) and then read from that when the Activity is resumed. This would ensure the proper theme is selected regardless of how the user gets to the Activity.
EDIT:
Note that the Activity framework methods are public not because they should be accessed at any time or by other classes, but because that is required for them to be implemented in your app. They are not intended to be invoked outside the framework.
You should note that in the official documentation for Activity none of the methods you are calling are listed as "Public Methods" (http://developer.android.com/reference/android/app/Activity.html#Activity()). You are using them in an unsupported way. However, I only point this out to make you aware of it and that it is not a generally accepted approach to solving this problem.
This is exactly in line with the documentation.
http://developer.android.com/training/basics/activity-lifecycle/starting.html
If you look at the chart, onResume gets called when returning to an activity no matter what but onStart doesn't.
if you want to change UI related component then you must use OnResume method instead of recreating all activities. like following.
#override
onResume()
{
textview.setText("Change text When activity resumes");
}
Colleagues above responded very well.
The behavior you reported. The onstart and onResume not be called. I've watched it happening to Hot Code Swapping. It is worth stopping the application and call the rebuild.

When is it safe to update the UI?

I feel like this should have been answered by the documentation in the Activity class, but I'm still not positive -- when is it actually safe to update the UI of an Activity (or a Fragment)? Only when the activity is resumed, or any point between being started and stopped?
For example, the Activity docs state:
The visible lifetime of an activity happens between a call to onStart() until a corresponding call to onStop(). During this time the user can see the activity on-screen, though it may not be in the foreground and interacting with the user. Between these two methods you can maintain resources that are needed to show the activity to the user. For example, you can register a BroadcastReceiver in onStart() to monitor for changes that impact your UI, and unregister it in onStop() when the user no longer sees what you are displaying. The onStart() and onStop() methods can be called multiple times, as the activity becomes visible and hidden to the user.
From that reading, I would assume that even if a foreground dialog is displaying, I can safely update UI elements behind it.
EDIT
To clarify: the reason I ask is having been bitten by errors when firing off an AsyncTask, and attempting to update the UI in the onPostExecute method. Even though it runs on the UI thread, the user has navigated away from that view and I would receive an exception. I'm starting a new project now and trying to establish some guidelines around better AsyncTask idioms.
I guess this comes down to what you mean by "safe" to update the UI. For elements on the Activity screen, they can be updated whenever, even if your Activity is not in the foreground (but make sure to update from the UI Thread).
However, the issue that will trip you up is saving state: onSaveInstanceState.
As you may know, the Activity that is in the background may be destroyed by the OS to free up memory. It will then be re-created when you come back to it. During this process, the onSaveInstanceState method will be called. If the OS does destroy the Activity, any changes you made to the UI State after the call to onSaveInstanceState will not be persisted.
For Fragments, you will actually get an IllegalStateException if you try to commit a FragmentTransaction after onSaveInstanceState. More info on that.
To summarize, you can update the UI of your activity at any point and try to gracefully handle the Fragment issues, but you may lose these updates when the Activity is restored.
So, you could say that it is only truly safe to update the Activity while it is in the foreground, or rather, before the call to onSaveInstanceState.
Edit in regards to Async Task onPostExectue
This is likely related to the issue I am referring to above with Fragment State Loss. From the blog post I linked to:
Avoid performing transactions inside asynchronous callback methods. This includes commonly used methods such as AsyncTask#onPostExecute() and LoaderManager.LoaderCallbacks#onLoadFinished(). The problem with performing transactions in these methods is that they have no knowledge of the current state of the Activity lifecycle when they are called. For example, consider the following sequence of events:
An activity executes an AsyncTask.
The user presses the "Home" key, causing the activity's onSaveInstanceState() and onStop() methods to be called.
The AsyncTask completes and onPostExecute() is called, unaware that the Activity has since been stopped.
A FragmentTransaction is committed inside the onPostExecute() method, causing an exception to be thrown.

Activity.finish() called but activity stays loaded in memory

When I run my app on the debugger, I get the main thread and 3 binder threads.
On a button click I call Activity.finish(), which looks like it ends the activity as the UI closes and goes back to the home screen.
However, in the debugger, it still shows the main thread and 3 binder threads as "(running)".
I am baffled to why this is happening. Even more so, it is causing my app to call Activity.onResume() when I run it again after exiting the app.
I currently override these methods in the Activity, but I call the appropriate super functions in each one:
onDestroy()
onPause()
onResume()
onSaveInstanceState()
Any help or advice regarding this is much appreciated!
You don't control when your app leaves main memory, the OS does. Look closely at Activity.finish...
Call this when your activity is done
and should be closed. The
ActivityResult is propagated back to
whoever launched you via
onActivityResult().
Note that is says nothing about memory. As to calling Activity.onResume, that's exactly what you would expect for the lifecycle; remeber that onResume is not just called after a resume but even when the app is first launched after onCreate.
While not exactly what you asked I suggest you read this article about exit buttons which goes on to say something very important
[Activity.finish] is exactly equivalent to hitting the back button.

Categories

Resources