When to save the state of an app - android

I am building an Android game. Now, I am saving all changes of the user state (matches in SQLite, user's preferences in SharedPreferences, and other data in files) in the onDestroy() method of the main fragment (that fragment should be alive all the time and can open other activities, such as a the account fragment or playing fragment).
If I exit the app via Back button, everything works fine since onDestroy() of main fragment is called.
The problem is when I exit via Home button, or when main fragment is killed from OS. In these cases, onDestroy() isn't called, so the state of the game isn't saved.
I know that I can resolve that if I save the game in the onPause() instead of onDestroy(), since it is always called. But the storage operation, in my case, is very big (SQLite + SharedPreferences + files, a lot of data) and do that in onPause() means inefficiency.
Is there any other way to manage this?

Have you tried this solution - http://nisha113a5.blogspot.com/2012/01/intercept-home-key-android.html?
Try to hook Home button pressing, and at this moment save user state.

Related

Stashed Activity means activity object does not exist?

I was looking at this page from "Android Programming" by big nerd ranch, and I was confused by the sentence beneath. It states that "when the activity is stashed, an activity object does not exist." This is confusing to me because when I open an app and press the home button, onPause() is called and the activity reaches a "Paused" state with its activity stashed in the OS, as shown in the figure. It must be still running in the background because onDestroy() is not called when I press the home button. In fact, when I open my task manager, I can see how the activity looked like when I pressed the Home button. What exactly do they mean by "activity object does not exist?" when it is clearly on paused state in the background?
THeir documentation looks to be a bit wrong and confusing. The official Android documentation doesn't talk about a "stashed" state, it would be the block "App process killed" in the documentation here
Basically, from the STOPPED state only, the OS may destroy your activity at any time. If it does this, is will call onSaveInstanceState. The Activity variable would then be invalid. At any time, it may then recreate a new Activity and call onCreate then onRestoreInstanceState on it, passing in the Bundle you save previously, to recreate the activity.
This is confusing to me because when I open an app and press the home
button, onPause() is called and the activity reaches a "Paused" state
with its activity stashed in the OS, as shown in the figure.
I would not say that this is "stashed". Your activity is alive and well, just paused.
It must be still running in the background because onDestroy() is not
called when I press the home button.
That's right. When you are hitting the home button you are saying to the OS "Hey I'm going somewhere else, but I'm not necessarily done with this activity."
If you instead hit the back button, then you'll see onDestroy called. Here you are saying to the OS "Ok I'm done with this activity, do with it what you want."
What exactly do they mean by "activity object does not exist?" when it
is clearly on paused state in the background?
The stashed state is entered when the OS needs to destroy your activity without you "telling" it to do so (i.e. hitting back button). This happens when your device goes through a device configuration change. A classic example is rotation. This also happens if the OS needs to free up memory. In this case onSaveInstanceState will be called to capture the state of your activity in a Bundle. The stashed state is then the preservation of this Bundle and the class name of your activity. The actual Activity object is marked for garbage collection. Then given just the Bundle object and the class name of your activity, the OS can create a new instance of your activity if the user returns to it.
One take away is that you don't have to implement onSaveInstanceState yourself unless there is specific information you want preserved. Some components of the view hierarchy will automatically add information about themselves to the Bundle because the super Activity.onSaveInstanceState will still be called. From the docs:
The default implementation takes care of most of the UI per-instance
state for you by calling onSaveInstanceState() on each view in the
hierarchy that has an id, and by saving the id of the currently
focused view (all of which is restored by the default implementation
of onRestoreInstanceState(Bundle)). If you override this method to
save additional information not captured by each individual view, you
will likely want to call through to the default implementation,
otherwise be prepared to save all of the state of each view yourself.
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
You can check the source here:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/app/Activity.java#1371

App stays in the background and memory was taken by other app,then click the app to front,what will happen in detail?

The detailed question is :
1.Whether the activity clicking order will get restore.In other words,if i click the back button again and again, whether the app's activity order will be normal.
2.what life cycle in activity will be triggered in last activity?Is it the same with the normal activity jump?
3.Was the state stored in physical memory(like sdcard)?How can i judge whether the important state was lost.
Taken from here:
Once an activity starts it goes to onCreate -> onStart -> onResume. If you minimize an activity (usually with the Home key) it will run onPause -> onStop and when android runs out of memory (because new app needs memory) then android will call onSaveInstance (where you save all the data you want) on your activity, then it will destroy it, calling onDestroy.
The next time the activity runs it will start again from onCreate and the rest, but it will pass a Bundle on the onCreate with the data you saved previously, for you to restore them. It will also run onRestoreState which gets the Bundle as well (you can use either one).
Basically, if onRestoreState runs, it means your app is restoring, or inside your onCreate check if the given Bundle is null, if it isn't then your activity is resuming.
I'm not sure if data are saved on sdcard, but I guess they are saved somewhere on physical memory, so android can free some RAM for another app.

onSaveInstanceState() not called on custom view when app is moved to background

In an app I am developing, I have a custom view in which I need to save the instance state when either the screen configuration changes or the app is moved to the background. I implement onSaveInstanceState() and onRestoreInstanceState(Parcelable savedInstanceState) and in the case of screen configuration changes, the instance state is saved and restored perfectly. However, when the app is moved to the background, onSaveInstanceState() is not called. This means I have no saved instance state when the activity is brought to the foreground again. My question is then:
Why is onSaveInstanceState() not called when the app is moved to the background, and is it possible to make my view call onSaveInstanceState() when the app is moved to the background?
It occurs when you press the back button to leave the activity. –
Zero
When using the Back button to leave the application the onSaveInstanceState method is not called by the Android system, this is expected system behavior. The back button is meant to stop your app (Read: activity).
The Back button finishes your Activity and there is no need to save app state. But if there is reason to to this then you should override the onStop method for example and save data to the file system there.
Sources:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
(Recomended read)
There are a few scenarios in which your activity is destroyed due to
normal app behavior, such as when the user presses the Back button or
your activity signals its own destruction by calling finish().
As per my knowledge, when app enter into background, on Activity it calls onPause() method. So please try by moving your code to onPause() method.

Android back key not letting me save activity state

Quick question.
I have an activity that calls my save function at the proper moments, onPause and onSavedInstance.
The onPause happens if the activity leaves the foreground and the onSavedInstance before being killed.
My activity saves the state perfectly if the user presses the "home" key but if he presses
the "back" key the onPause still happens and consequently some fields are saved in
the activity class attributes.
The problem is that when the User goes back to the activity the onCreate is called meaning (for what I understood) that the class is instantiated and therefore its attributes are null again.
If the onSavedInstance was called when the back key was previously pressed I could use it to save the activity state but it's not.
So my question is, when the user presses the back key how can I save the activity sate withou using sqlite, file saving and other persistance methods?
When the user presses the BACK button, your foreground activity is destroyed. That activity will be called with onPause(), onStop(), and onDestroy(). That activity object will then be garbage collected (unless you introduced a memory leak).
onSaveInstanceState() will be called periodically if there is a chance that the activity will be destroyed shortly but in a way where the user might be able to navigate back to it. The prominent case for this is during a configuration change, such as rotating the screen.
What you should be doing in onPause(), if anything, is persisting data using "sqlite, file saving and other persistance methods". Once onPause() is called, there are no guarantees that this activity will stick around, or that your entire process will stick around. Anything you value, therefore, should get written out to persistent storage.
The "state" for onSaveInstanceState() would be things that affect the activity's UI but are not part of the persistent data model. Much of this is handled for you automatically by Android's built-in implementation of that method (e.g., the text in an EditText), but you can add your own information to the Bundle if you wish. However, your instance state is not your data model, so anything you want to stick around needs to be written out to persistent storage.
If your concern is performance, you are welcome to cache data in static data members/singletons, assuming you do not introduce a memory leak. But, again, once onPause() is called, your process may be terminated at any point in time. Your static data members can only be a cache; your data model must be something persistent.

Reload application data when the android app comes into foreground..?

Here is the scene what i am facing..when i press home key it saves the current state of the current activity..so when my app comes in foreground, onResume() of that particular activity gets called who's state was saved. So if an app with say 10 activities are there then, we will need to write reload of app data in each activity's onResume()..is there a way to specify a reload of app data in one activity only..?
Jitesh,
Yes, this is possible. You will probably want to perform the reloading of application data in your Activity's onResume() function. See Android Activity Lifecycle.

Categories

Resources