I'd like someone to help me with this question regarding an application lifecycle.
My App starts an activity StoryActivity, that can launch other instances of itself, so when the user presses the BACK button, returns to the previous StoryActivity.
I maintain a cross-activity cache in a static hashmap that I'd like to flush on the activity's OnDestroy, but only if this is the last of my spawned activities, i mean, only if the user has destroyed all the stacked (linked) stories and this is the only one left. Kind of an application shutdown.
Do I need to subclass Application, or what's the best practice for my intentions?
I'd like to avoid tracking myself the activity nesting if possible, relying on the android standard lifecycle as much as possible.
Thanks in advance.
Related
So, for my Android course this semester we're making an app of our own choosing, and due to a lack of ideas I decided to go with a text-adventure styled game. Nothing too complicated, I know. I'm making sure to be creative and incorporate a lot of different functions of the phone, such as the accelerometer and the camera. But I digress.
I've started planning out how the app should work, and how I should go about coding it, but I've come upon an obstacle fairly early that I need to find a solution for. I'm planning on creating it so that the player is sent from activity to activity, which I think is the best way to go about it, unless I do an endlessly scrolling activity that fills out as the player progresses. And thus, I need a way to make it so that when the player closes the app completely it will "continue" on the last activity before shutdown, so the progress is saved in a way.
I'm not sure if this is possible to do, and if so, are there any other ways I can achieve the same sort of result?
There is no way that you can change your starting activity programmatically. You can save the activity that you want to start with in a file and redirect to this activity from your main activity every time your application starts (on the onCreate() method of your main activity).
As it says here.
As someone has suggested, save the current state (ie: what Activity is currently shown) in SharedPreferences. When the user launches your app, the root Activity (the one with ACTION=MAIN and CATEGORY=LAUNCHER) will be started. In onCreate() of the root Activity, read the saved state from the SharedPreferences and launch that Activity immediately.
After reading through all the questions on SO regarding this topic i am extremely annoyed by this.
Crashes will happen, no one writes perfect code. And there are apps that require a certain logical hierarchy. The best example is the login-screen idea, where you are in some activity doing something on a server and now the app crashes. After a restart, the app lost all its login-session data and saving it might not be the safest idea. So presenting the user with the login screen after a crash would be the best and most logical thing to do. The best user experience.
However Android decides to remember the Activity stack but only restart the last working activity with a "blank" application under it.
The only viable option i see would be to check in EVERY single activity if some login state is available or not and if not, start the login (launcher) activity with a clear-top or clear-task. But this almost forces you to write a base extends Activity class in which this behavior is implemented and then all activities have to extend that. But what if, for some reason, you cannot extend it because you need to extend some other type of activity?
There is android:clearTaskOnLaunch but this happens every single time the user returns from exiting via home button. There is the antagonist finishOnTaskLaunch that finished an activity every time the user presses the home button. So the Android devs are aware that sometimes one would like the app to appear in a certain state after exit but a crash seems to be exclusive to all that.
Using a custom UncaughtExceptionHandler gives me some chance to act after a crash but as the apps state is unrecoverable i can only perform certain tasks that will happen in addition to Android very own behavior.
So my simple question is, if there is any way, that is built into Android, that allows me to change the after-crash-behaviour of Android in a natural way that does not depend on the version it's running (to some extent ofc) and will result in a somewhat smooth user experience.
I would say the proper way of obtaining the result you would like would be to provide a proper parent or up navigation stack. You can read about it more here https://developer.android.com/training/implementing-navigation/ancestral.html.
But the gist of it would be to use the idea of parent activities to provide proper back navigation. If the activity already exists it will just go back to it, if it doesn't (such as in the crash scenario) it will launch the correct activity when the user navigates back.
NavUtils is a handy class to help build this behavior and is part of the support library which would work on a range of different API levels.
I'was wondering a simple thing. I'm making an android app and I started asking my self about memory usage.
What does the android OS make when I call a new intent??
Imagine i have an intent with only one button and this button onclickmethod is making a new intent of the same activity.
If on click I do this??
Intent activityN = new Intent(Activity.this,Activity.class);
startActivity(activityN);
is the firstActivity killed or does android keep it?
And if I click 50 times??
thanks for your answers
Activities life cycle is a tricky topic.
In most cases the activity will be kept in memory, but in some cases Android may decide to destroy it to reclaim resources. You have no control over this behaviour, which may change between OS versions and even hardware configurations. Don't try to fight it - embrace it.
Activity state is saved in onSaveInstanceState(Bundle), which is called before placing the activity in a background state.
When the Activity is about to be shown - but was destroyed to reclaim resources - it can be recreated using savedInstanceState in onCreate() method. You are expected to handle this situation. Most programmers don't care, which leads to strange errors on screen rotations and after longer periods of inactivity.
You may think about this mechanism as a serialization/deserialization scheme, that allows Android to optimize memory usage, discarding the data that can be recreated on demand (such as UI layout) and saving only things that cannot be recreated, such as UI state (entered text, checbox states, etc).
Since Activity destruction is rather unpredictable under normal conditions, Android provides special developer's option to always destroy activities when possible. This allows you to properly handle all corner cases around activity life cycle without too much effort. Explore your device's developer options.
You may want to check out those articles to learn more about the topic:
http://developer.android.com/training/basics/activity-lifecycle/index.html
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
Going back to your question about clicking the button 50 times... it will probably create 50 instances of activity, stacked on top of each other. It may be the case that Android starts to destroy first activities to make room in memory for new ones. Let's say that the device have memory for only 49 activities. You start 49 - all are kept in memory. You start 50th one and the 1st is going to be destroyed. Her state is saved in Bundle, so when you press back 49 times, the first one will be re-created from this saved bundle.
That depends on the flags you are supplying with your Intent.
If no flags then every startActivity creates a new Activity.
However, there can be FLAG_ACTIVITY_CLEAR_TOP orFLAG_ACTIVITYY_SINGLE_TOP flags.
It's boring to repeat it all here, have a look at the docs:
http://developer.android.com/guide/components/tasks-and-back-stack.html
Android keeps the first Activity. That's why when the second Activity is finished you can return (with results even) to the same state. If you clicked the button 50 times, you'd start 50 new activities. YOu generally want to avoid that, so its a good idea to disable the button after the first press. Luckily your new activity should quickly start and cover up the button, so 50 is hard to do (although 2 or 3 isn't).
I found and read a lot of articles talking about global variables in Android, some of them suggests using an subclass of Application + declare it in the manifest file as a glbal variable container.
But some articles mentioned that This class could also be killed when system memory gets low, is this correct?
So, is it 100% reliable to use an Application subclass as a global variable container? And could somebody give me a link to some documents explaining the life cycle of an application in Android (not activity)?
EDIT:
Thanks for the answers, I think I need to explain a bit more of my question.
The situation is, I just want to share a global String variable, Activity A modifies it, and activity B reads it.
When B is currently visible and user receives a call,
If A and B are killed but Application keep untouched (is this what Google calls an empty process?), I'm OK with it.
If A, B, and Application class are all killed and when user come back my app gets a clean start, I'm OK with it.
Which I'm not OK with it is, everything was killed including the Application class, when user come back my app doesn't start fresh, I mean, it starts from Activity B, will this happen? then should I start A manually or let Application class to do the initiation? none of these ideas looks good to me...
The answer is both "YES" and "NO" - the Application class can be used as a "global variable container" in that all activities and classes can rely on it.
However, you cannot rely on the Application class (or any other class) to persist indefinitely. In other words, if the user answers their phone, your application could be destroyed and then re-created when the user completes the call and returns to your app. So, you definitely cannot rely on it to persist data, but you can rely on it to provide global access to data when you app is active.
This is the Android documentation:
http://developer.android.com/training/basics/activity-lifecycle/index.html
This is a really good post on it - read the SECOND highest voted response, in addition to the "accepted" response:
Using the Android Application class to persist data
It explains pretty clearly how your app can be killed/destroyed whether you expect it or not.
EDIT:
To clarify, if you have a variable (call it "myVar") in the Application class and a user sets it in Activity A, then proceeds to Activity B, Activity B will be able to read the change.
If Android "destroys" the application class, which can occur anytime the user is not in your app (and in rare instances even if they are...), the app will be reconstructed so that the Activity Stack is still valid but "myVar" is not set, unless you persist the data.
In other words, Android will recreate the Application class and Activity B, but there is no guarantee that it will recreate Activity A until the user does something to destroy Activity B. Also, it will certainly not "replay" the user actions in Activity A in order to recreate the app state, and in your case that means "myVar" is not reliable.
If you read the references provided, you will see that this is the case (and also I have tested it).
EDIT 2:
To persist data, consider SQLite (which is pretty complicated and there are many references) or SharedPreferences:
How to use SharedPreferences in Android to store, fetch and edit values
This class could also be killed when system memory gets low, is this correct?
Yes.
So, is it 100% reliable to use an Application subclass as a global
variable container?
If you want to use it to pass values it is not reliable.
why?
EDIT:
Which I'm not OK with it is, everything was killed including the
Application class, when user come back my app doesn't start fresh, I
mean, it starts from Activity B, will this happen?
yes. It is possible that you set a value in your application from activity A and then when you are in Activity B user leaves your app and after a while android kills your process. then user comes back wants to look at your app. android again recreates application and activity B but not Activity A and instead of fill the application variable with what has passed Activity A to it, it recreates it from default initialization. So simply you missed what has passed or set by Activity A.
Don’t Store Data in the Application Object
Has anyone come across a flowchart of the Lifecycle of the whole Application?
I've seen the Lifecycle flowchart for a single Activity
I know there is an object Application where it is possible to create and keep global variables accross Activities. This must be created outside the Activity Lifecycle.
I also read in some post that the first Activity is special and it gets destroyed last of all.
I also know that background tasks still execute even if the parent Activity is paused/stopped. Also would like to see their lifecylce.
It would be nice to have a complete graph of how Android OS creates and manages ALL the application components from birth to death.