In onCreate(Bundle savedInstanceState), there`s already super.onCreate(savedInstanceState).
API says it restores states when create activity after destroyed.
But I have to override onSavedInstanceState(Bundle outState) for restore specific states.
Why?
What kind of informations are saved in savedInstanceState with method onCreate() and onSavedInstanceState()?
I'm so confused!
By default, when your device changes configuration (for example, devices rotates, you changed language settings, etc.), your foreground Activity is recreated, and all you Activity data is lost. For example, if you have a member variable mVariable that was assigned some value, after configuration change you will lose its value. That's why you need to save important data to savedInstanceState and re-init it from onCreate() method. You simply check whether savedInstanceState is not null, and if so, you init your values from savedInstance, else - init with default values.
Further reading: http://developer.android.com/training/basics/activity-lifecycle/recreating.html
onSaveInstanceState() is called before your activity is paused. So any info that it needs after it is potentially destroyed can be retrieved from the saved Bundle. The Bundle is a container for all the information you want to save. You use the put* functions to insert data into it. To get the data back out, use the get* functions just like the put* functions. The data is stored as a name-value pair. There isn't a specific use of this element, you can use it in any case (save a name, a number or whatever you need to have again when the use open again the app)
Related
I was left with some questions regarding ViewModels after reading this:
https://developer.android.com/topic/libraries/architecture/saving-states
It says here that you should use a combination of both a ViewModel for configuration changes (like screen rotation), and using onSaveInstanceState() for all other cases where an activity is destroyed and then recreated in order to save the UI state.
My question is how do we know the way to restore the state when onCreate(Bundle) is called - should I use the ViewModel or should I use the bundle received as a parameter? When the configuration changes, onSaveInstanceState() is also called, and obviously onCreate() is always called.
If I only restore the state from a ViewModel, it won't always remain with the correct data (since the activity could have been destroyed due to other reasons than configuration changes). If I only use the bundle I save in onSaveInstanceState() then why would I use a ViewModel to begin with?
I think it's good to think of this sources as a chain.
You have 2 sources of data - ViewModel, that is faster but lives less and saved instance state that is slower but lives longer.
The rule is simple - try using your ViewModel and if it is not populated use the bundle from onSaveInstanceState().
When you do val model = ViewModelProviders.of(this).get(MyViewModel::class.java) in onCreate() you can check if you get a new instance of viewModel. Then, if it is a new instance (i.e. it's data fields are empty) you can get some basic data from your bundle, like content id, and fetch data from the backend or database based on that id, populate your new ViewModel with it and then populate your activity from the ViewModel (if you are using LiveData it will be very natural).
Next time onCreate is called you repeat the process, either populating your activity from ViewModel or populating your ViewModel using data in the Bundle and then populating your activity from your ViewModel.
Update:
Actually there is very similar approach described in the official docs. The only difference is that you pass the bundle to ViewModel and it decides if it needs fetching data, I was not specific about this mechanism.
Is there technically any reason why I should use onRestoreInstanceState? Could I not do all the restoration in onCreate by checking if the savedInstanceState bundle is null? What is the primary benefit of using onRestoreInstanceState over doing everything in onCreate?
onRestoreInstanceState
This method is called after onStart() when the activity is being re-initialized from a previously saved state, given here in savedInstanceState. Most implementations will simply use onCreate(Bundle) to restore their state, but it is sometimes convenient to do it here after all of the initialization has been done or to allow subclasses to decide whether to use your default implementation.
onRestoreInstanceState guarantees you receive a non-null Bundle object also in the lifecycle of activity it's called after onStart
But onCreate: you should always check if the Bundle object is null or not to determine the configuration change and as you know it's called before onStart
So It's all up to you and depends on your needs.
Mostly I tend to use onCreate(Bundle) to restore activity state, but if you have some initializations after which you want to restore the state its better to use onRestoreInstanceState() which offers much flexibility to restore state by the subsclasses those are extending the current activity. Also to be noted onRestoreInstanceState() is called after onStart() whereas onCreate(bundle) is called before that.
If you have huge data you can implement ViewModel class which handles the UI controller logic. ViewModel objects are automatically retained during configuration changes so that data they hold is immediately available to the next activity or fragment instance. For example, if you need to display a list of users in your app, make sure to assign responsibility to acquire and keep the list of users to a ViewModel, instead of an activity or fragment.
It also provides de-coupling and making your activity or fragment serve a single purpose rather than handling excessive responsibility of UI logic.
In my opinion, we can see this doc Restore activity UI state using saved instance state .
here are some points
1.Both the onCreate() and onRestoreInstanceState() callback methods receive the same Bundle that contains the instance state information.
2.Instead of restoring the state during onCreate() you may choose to implement onRestoreInstanceState(), which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null:
Usually fragment states are saved using onSaveInstanceState() and restored with onViewStateRestored() or by using a state instance fragment. However I noticed I can save fragment variable data by declaring the variables static. Obviously this won't work with view components but for primitives it seems to work fine. I wanted to know whether this static data is guaranteed to be preserved without saving it in onSaveInstanceState().
No it is not guaranteed.
When for example Android decides to kill your process, the onSaveInstanceState() is called and the bundle will be available when you get back to your app as savedInstanceState, however all of the static variables will lose their values when your app gets killed. This applies to all of the static variables.
I would like to know if there is a method to Save a Custom Class while rotating in an Android app.
I want to save all instanced object called of the MatrixGame class...someone can help me?
Thanks
Since the Fragment lifecycle is independent - when you're using a Fragment you can set it so it doesn't get destroyed upon configuration changes.
As you noticed, the Activity class gets destroyed and re-created when you rotate the app (or apply other configuration changes), if you want to persist the Activity state you can use sqlite and save whatever you need in the onPause() method. Then in the onCreate() method check the DB for last known state.
If you want to avoid saving the state "forever" (meaning, the user turns off the app and tomorrow when she turns it back on - you want to start fresh and not load the last known state) you can add a timestamp and set a threshold which, if passed, the data is considered stale and gets disregarded.
Two comments:
As #saprvade wrote, Fragments gets destroyed by default, in order to prevent it you should call: setRetainInstance(true)
In case you want to implement #saprvade's other suggestion (have the activity ignore rotation changes) you can see the following explanation of how to implement: https://stackoverflow.com/a/456918/1057429
You should serialize your object. You can implement Parcelable or implement Serializable (Parcelable is several times faster). Then you will be able to put it in a Bundle in onSaveInstanceState and restore it in onCreate or onRestoreInstanceState.
Also, you can serialize your object to String, e.g. json string.
Another option would be to store your object in a database or a file. It depends on your needs.
If you don't want to recreate this object on screen rotation you can change the lifecycle of your Activity by adding a configuration change flag in AndroidManifest.xml. If we are talking about a Fragment, you can call setRetainInstance(true) to avoid fragment recreation on rotation.
What is the different between to reinitialize data of Activity in onCreate() and onRestoreInstanceState()
I am getting bundle in oncreate aslo.So My question is why I am not able to set data in oncreate method while the same thing is done in onRestoreInstantstate..Then what is the use of bundle object in oncreate i went through different tutorial but not got relevant answer so please if any one know the difference that where does we use the implementation to reinitialize the data of activity that whether it should be in onCreate or onRestoreInstanceState................please let me know
#numan salati Said:
onRestoreInstanceState is redundant because you can easily restore state in onCreate.
Having said that here is what the official doc says for
onRestoreInstanceState:
Most implementations will simply use onCreate(Bundle) to restore their
state, but it is sometimes convenient to do it here after all of the
initialization has been done or to allow subclasses to decide whether
to use your default implementation.
So for best practice, lay out your view hierarchy in onCreate and
restore the previous state in onRestoreInstanceState. If you do that,
anyone who subclasses your Activity can chose to override your
onRestoreInstanceState to augment or replace your restore state logic.
This is a long way of saying onRestoreInstanceState serves as a
template method.
Here