Where is a Bundle variable saved in Activity? - android

public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putInt("x", x);
}
When I save a Bundle, Where is the Bundle variable exactly saved? I can't find it anywhere

In addition to android reference, you can read the source code to understand what has happened here.
protected void onSaveInstanceState(Bundle outState) {
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
In the source code, it's clear to see the state will be managed by Application. When the Activity is destroyed, the Application can help save relevant states. But, if you ever met this situation that Application was killed, you would find all states were lost. So, I think all states are kept in memory, not file like preference.

Well, I don't think you will find it and I don't expect to be referenced directly somewhere.
However its content will be available in onCreate(savedInstanceState) when the activity is recreated. Taken from its documentation: savedInstanceState: If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null
Another place to look for its content is onRestoreInstanceState(savedInstanceState)

i am not sure I think you must set the int,string or whatever you want
so as to save it into int
Let me show you an
EXAMPLE
public void onSaveInstanceState(Bundle state){
super.onSaveInstanceState(state);
Int i = 1;
state.putInt("s",i);
}

Related

SavedInstanceState is always null in fragment

I have a fragment attached to the activity using XML (and setContentView() in activity). A have a problem because I have very dynamic views in my fragment, so when orientation changes
I must restore all states of views.
I have problem because I'm using something like that:
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("restore", true);
outState.putInt("nAndroids", 2);
}
But after orientation change when methods with param Bundle savedInstanceState are called (like onCreateView etc) my savedInstanceState is always null.
I'm not a noob in the Android but now I'm very angry because of this problem...
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState == null) {
//smth
} else {
// smthelse THIS IS NEVER REACHED BECAUSE BUNDLE IS ALWAYS NULL
}
getListView().setDivider(getResources().getDrawable(R.drawable.list_divider));
}
All the problem was in that I don't declare android:id for the fragment in XML. Android needs ID or TAG to recognize stored fragment and reproduce all elements in it. So guys, remember - every instance of fragment needs unique id or tag!
Also, when setRetainInstance(true) is declared then bundle should always return null.
I had a similar problem where I was always getting savedInstanceState as null inspite of supplying the bundle to the Fragment.
The only solution that worked for me was to do
myFragment.setArguments(bundle)
with my bundle from the Activity and do a
Bundle bundle = this.getArguments();
in onCreateView of the fragment.
Hope this helps someone else.
For Fragment :-
use this for save state of fragment on orientation.
onCreate(Bundle save)
{
super.onCreate(save);
setRetainInstance(true);
}
See this tutorial :-
http://techbandhu.wordpress.com/2013/07/02/android-headless-fragment/
For Activity:-
When you start your application, in onCreate, your bundle object is null, so you have to put a check like below and when you rotate your screen then onSaveInstance is called and your bundle object is initialized
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
if (savedInstanceState != null) {
boolean t = outState.getBoolean("restore");
int s = outState.getInt("nAndroids");
}
}
First you should put your data, then call super.onSaveInstanceState(outState);
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean("restore", true);
outState.putInt("nAndroids", 2);
super.onSaveInstanceState(outState);
}
And be sure that activity has not nohistory property in AndroidManifest.xml or set it to false.
<activity
android:noHistory="false">
If you are trying to use outState to save the state and destroy the fragment by navigating to another fragment, it will not work, you have in this case to save your state permanently in either sharedPreferences or if it's big and you want to be more organized you can use any persistence lib like Room, Realm, ...etc.
When should use outState and savedInstanceState only to make Fargment/Activity survive config change(rotation for example) or processes being killed by the OS when the app is in background for example.
Ok I know this is an old post but I couldn't find the right answer for me here nor many other places, so I am posting how I fixed my case.
So My Fragment is inside an Activity. And I originally tried to save Bundle only in Fragment and retrieve it at onCreateView. However that was the problem.
I fixed this by initiating myFragment object in activity and put that object to activity Bundle at onSaveInstanceState(). Then retrieved it at onRestoreInstanceState(). I used getSupportFragmentManager().putFragment/getFragment. Then the savedInstanceState in fragment was no longer null.

onRestoreInstanceState is never called / savedInstanceState is always null

I have looked in all the site and I don't understand why it's not working on my side.
Please find my source code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
Log.e("EVERYTHING", "OK");
}
}
and
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("test", "titi");
Log.e("Save", "titi");
super.onSaveInstanceState(outState);
}
I launch my appli, then press the home button, then restart my phone and launch the appli again, but the savedInstanceState is null.
Could you please help me.
Regards
onSaveInstanceState is used to persist state in memory so it's not suitable for situations like you described above. If you restart your phone, obviously all state store not persistently (only in memory) is not preserved.
If you want to store state this way, you should look at something persistent, e.g. shared preferences or SQLite.

Super should be called at the end of the method

#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
((CustomApplication) getApplication()).detach(this);
}
While generating PMD report, i got this Error: Super should be called at the end of the method. Normally you would eventually keep the super method at the top(First Statement) so that its parent class is first called initialized.
Normally you would eventually keep the super method at the top(First
Statement) so that its parent class is first called initialized.
The following code snippet shows you how Activity#onSaveInstanceState(Bundle outState) looks like. You can see that it only saves the Bundle you passed in as an argument by calling super.onSaveInstanceState(outState);. So it would make no sense to call the super method before actually saving something inside the Bundle.
protected void onSaveInstanceState(Bundle outState) {
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
According to this SO, it doesn't matter where you call it as long as the key do not collide. They should be equivalent.
So long as your keys do not collide (e.g., ID being the same as something Android uses internally), the two are identical.
But with that being said, Google's documentation about The Activity's Lifecycle shows adding this at the end. I would still follow that though:
// invoked when the activity may be temporarily destroyed, save the instance state here
#Override
public void onSaveInstanceState(Bundle outState) {
out.putString(GAME_STATE_KEY, mGameState);
out.putString(TEXT_VIEW_KEY, mTextView.getText());
// call superclass to save any view hierarchy
super.onSaveInstanceState(out);
}

Fragment saveInstanceState is coming as null after orientation change

I have an activity with action bar tab. Each tab contain a fragment. Now when I rotate my device, bundle in my corresponding fragment is coming as null. This is taken care when I using device post android 3.2, but it is happening when device is Andoird3.0. I am having a headache after working on this issue. I crossed check various link on SO, but no help. Although I have given enough details, still will provide some code snippet as at various cases user ask for code snippet.
In my fragment class I am storing this value
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putBoolean("textboxVisible", true);
}
this is storing one boolean variable which it retrived as below.
/**
* Function called after activity is created. Use this
* method to restore the previous state of the fragment
*/
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null)
{
//restore the state of the text box
boolean textboxVisible = savedInstanceState.getBoolean("textboxVisible");
if (textboxVisible)
{
//do some stuff
}
}
}
but after rotation savedInstanceState is coming as null.
I don't what is going wrong. I have read in some document that below 3.2 the onCreateView() of
fragment is not called with bundle value. But to deal with this. Any help will be appreciated.
if you use setRetainInstance(true) the savedInstance bundle is always gonna be null after orientation changed. SO you cannot really save something with it, but what you can do if you need to save something, is to put it in a data member of the fragment, because setRetainInstance(true) preserves the fragment and doesn't destroy it, so after the device was rotated you gonna have the same values.
Try to get the savedInstanceState in onCreate of the Fragment.
Like
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
if (savedInstanceState != null) {
// IT MUST NOT BE NULL HERE
}
}
Please try... i hope it will work

How to use onSavedInstanceState example please

I'm confused when it comes down to saving a state. So I know that onSaveInstanceState(Bundle) is called when the activity is about to be destroyed. But how do you store your information in it and bring it back to its original state in onCreate(Bundle savedInstanceState)? I don't understand how this bundle will restore information. It would be helpful if someone can provide an example.
The Dev guide doesn't do a good job of explaining this.
public class Conversation extends Activity {
private ProgressDialog progDialog;
int typeBar;
TextView text1;
EditText edit;
Button respond;
private String name;
private String textAtView;
private String savedName;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.dorothydialog);
text1 = (TextView)findViewById(R.id.dialog);
edit = (EditText)findViewById(R.id.repsond);
respond = (Button)findViewById(R.id.button01);
if(savedInstanceState != null){
savedInstanceState.get(savedName);
text1.setText(savedName);
}
else{
text1.setText("Hello! What is your name?");
respond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
name = edit.getText().toString();
text1.setText("Nice to meet you "+ name);
}
});
}
}
#Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
outState.putString(savedName, name);
}
}
The Bundle is a container for all the information you want to save. You use the put* functions to insert data into it. Here's a short list (there are more) of put functions you can use to store data in the Bundle.
putString
putBoolean
putByte
putChar
putFloat
putLong
putShort
putParcelable (used for objects but they must implement Parcelable)
In your onCreate function, this Bundle is handed back to the program. The best way to check if the application is being reloaded, or started for the first time is:
if (savedInstanceState != null) {
// Then the application is being reloaded
}
To get the data back out, use the get* functions just like the put* functions. The data is stored as a name-value pair. This is like a hashmap. You provide a key and the value, then when you want the value back, you give the key and the function gets the value. Here's a short example.
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("message", "This is my message to be reloaded");
super.onSaveInstanceState(outState);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
String message = savedInstanceState.getString("message");
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
}
Your saved message will be toasted to the screen.
One major note that all new Android developers should know is that any information in Widgets (TextView, Buttons, etc.) will be persisted automatically by Android as long as you assign an ID to them. So that means most of the UI state is taken care of without issue. Only when you need to store other data does this become an issue.
From Android Docs:
The only work required by you is to
provide a unique ID (with the
android:id attribute) for each widget
you want to save its state. If a
widget does not have an ID, then it
cannot save its state
A good information: you don't need to check whether the Bundle object is null into the onCreate() method. Use the onRestoreInstanceState() method, 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
Store information:
static final String PLAYER_SCORE = "playerScore";
static final String PLAYER_LEVEL = "playerLevel";
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(PLAYER_SCORE, mCurrentScore);
savedInstanceState.putInt(PLAYER_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
If you don't want to restore information in your onCreate-Method:
Here are the examples: Recreating an Activity
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
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(PLAYER_SCORE);
mCurrentLevel = savedInstanceState.getInt(PLAYER_LEVEL);
}
Basically onSaveInstanceState(Bundle outBundle) will give you a bundle.
When you look at the Bundle class, you will see that you can put lots of different stuff inside it. At the next call of onCreate(), you just get that Bundle back as an argument.
Then you can read your values again and restore your activity.
Lets say you have an activity with an EditText. The user wrote some text inside it.
After that the system calls your onSaveInstanceState().
You read the text from the EditText and write it into the Bundle via Bundle.putString("edit_text_value", theValue).
Now onCreate is called. You check if the supplied bundle is not null. If thats the case,
you can restore your value via Bundle.getString("edit_text_value") and put it back into your EditText.
This is for extra information.
Imagine this scenario
ActivityA launch ActivityB.
ActivityB launch a new ActivityAPrime by
Intent intent = new Intent(getApplicationContext(), ActivityA.class);
startActivity(intent);
ActivityAPrime has no relationship with ActivityA.
In this case the Bundle in ActivityAPrime.onCreate() will be null.
If ActivityA and ActivityAPrime should be the same activity instead of different activities,
ActivityB should call finish() than using startActivity().
If Data Is not Loaded From savedInstanceState use following code.
The problem is url call is not to complete fully so, check if data is loaded then to show the instanceState value.
//suppose data is not Loaded to savedInstanceState at 1st swipe
if (savedInstanceState == null && !mAlreadyLoaded){
mAlreadyLoaded = true;
GetStoryData();//Url Call
} else {
if (listArray != null) { //Data Array From JsonArray(ListArray)
System.out.println("LocalData " + listArray);
view.findViewById(R.id.progressBar).setVisibility(View.GONE);
}else{
GetStoryData();//Url Call
}
}

Categories

Resources