I'm trying to teach myself some android programming and I'm unable to get my app to save and load a users progress.
Currently I initialise my variables level and score in my activity. Then call this from my onCreate method:
if (savedInstanceState != null) {
// Restore value of members from saved state
playersScore = savedInstanceState.getInt(STATE_SCORE);
level = savedInstanceState.getInt(STATE_LEVEL);
} else {
playersScore = 0;
level = 0;
}
and finally I have a method for saving a bundle:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt(STATE_SCORE, playersScore);
savedInstanceState.putInt(STATE_LEVEL, level);
super.onSaveInstanceState(savedInstanceState);
}
For some reason my bundle wont save, any ideas on what I'm missing?
From the docs:
Note that it is important to save persistent data in onPause() instead of onSaveInstanceState(Bundle) because the latter is not part of the lifecycle callbacks, so will not be called in every situation as described in its documentation.
Have you looked at:
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
playersScore = savedInstanceState.getInt(STATE_SCORE);
level = savedInstanceState.getInt(STATE_LEVEL);
}
Also shouldn't:
savedInstanceState.putInt(STATE_SCORE, playersScore);
savedInstanceState.putInt(STATE_LEVEL, level);
be:
savedInstanceState.putInt("STATE_SCORE", playersScore);
savedInstanceState.putInt("STATE_LEVEL", level);
As putInt() requires a string and an int.
Related
My app needs to be able to dynamically create TextViews, so I need to be able to restore them if my app is ever GCed or switches orientations. The problem is I can't figure out how to restore the state of my TextViews. Saving their states with TextView.onSaveInstanceState() seems to work just fine, but when the Parcelable is passed to onRestoreInstanceState(), nothing happens and the resulting view is just blank. This is a short example which doesn't work:
public class MainActivity extends AppCompatActivity {
TextView v;
#Override
protected void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_main);
ViewGroup main = (ViewGroup) findViewById(R.id.main);
v = new TextView(this);
main.addView(v);
if (state == null) {
v.setText("A simple message.");
} else {
v.onRestoreInstanceState(state.getParcelable("message"));
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("message", v.onSaveInstanceState());
}
}
I have checked the value of state.getParcelable("message") in the debugger and it definitely has the required information. onRestoreInstanceState() just isn't using it. Any help at all would be appreciated.
EDIT: I screwed up with the debugger. The information was actually never written to the bundle. TextView.onSaveInstanceState() had returned an empty Parcelable. That was the real problem.
I figured it out. It the problem was with TextView.onSaveInstanceState()—not TextView.onRestoreInstanceState(). TextView.onSaveInstaceState() only saves the state if you explicitly ask it to by calling TextView.setFreezesText(true) first. SURPRISE! Thank you, Google. Also note that onRestoreInstanceState() doesn't restore the FreezesText property. Oh, Google. You're just so zany. What'll we do with you?
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:
Save Your Activity State:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
Restore Your Activity State:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
}
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(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
I am making a Sample of twitter integration ,i am fetching user information on click of button. Data is coming on screen it is working fine with portrait modeb but as i changed to landscape mode ,data loss.
how to solve this issue, i dont know how to use onSavedInstance method to solve this problem. please help
You need to override android default methods like onSaveInstanceState and onRestoreInstanceState check this example.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}
//you can retrieve saved values from here
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(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
click here to find more about this
I have created two activities A and B. In the Activity A, using onSaveInstanceState method I am saving bundle value ex(outState.putString("selectSaveDate", this.CalSelectedDate)) and going to the Activity B. When I hit back button to the Activity A , In the oncreate method the bundle value is null. I am unable to get my saved value in the oncreate method.
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.clear();
Log.i("bundleSave", "tester1" + this.CalSelectedDate);
outState.putString("selectSaveDate", this.CalSelectedDate);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null){
Log.i("todolist", "dsa" + savedInstanceState.getString("selectSaveDate"));
}
}
You only store data in a bundle in the OnSaveInstanceState method to persist data when your activity is destroyed and re-created (such as when rotating the screen or when the android os may decide to kill your activity if it is low on resources). When you launch activity B on top of your currently executing activity A, A is put in to a stopped state (therefore, your A activity is not destroyed). Also, when you come back from onStop, the next method that is called is onStart() (technically onRestart() is called be before onStart() but I find that callback is rarely ever implemented.
In conclusion, if your trying to keep persist data between launching an activity on top of your currently executing activity, you can just store that data in instance variables for that activity. If your trying to persist data between app launches then your going to want to look into storing data in Android's built in sqllite database or Android's SharedPreferences.
You should also obtain a real good understanding of the Activity lifecycle (its tricky but needed to code successfully in android):
http://developer.android.com/training/basics/activity-lifecycle/index.html
please try to Override onSaveInstanceState(Bundle savedInstanceState) and write the application state values you want to change to the Bundle parameter like this:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "How are you");
// etc.
}
it will get passed in to onCreate and also onRestoreInstanceState where you'd extract the values like this:
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}
or follow activity life cycle for better understanding.
Iam little bit amazed with this.I have an onResume() in my activity.Its called and works well in my emulator, but in a physical device samsung galaxy note for specific with jellybean installed,its not called.Instead onCreate() is called all the time.Why this happens?
public void onResume(){
super.onResume();
if(firsttime){
try {
Toast.makeText(getApplicationContext(), "Resuming Activity",Toast.LENGTH_LONG).show();
addReminder();
} catch(Exception exception) {
exception.printStackTrace();
}
} else {
firsttime=true;
}
}
This is my code.firsttime is a static boolean variable.It is used to prevent onResume() being called when app is started for the first time
Considering your current scenario, you should save variable in preferences instead of relying on activities lifecycle since lifecycle depends on many things.
Using static variable for this scenario is bad choice in general.I think this should solve your problem.
Try to print something inside the onResume and check it in LogCat.... the code inside onResume may be causing this.
or else can you elaborate your question?
I think here is what happens,
when your app not the Top app, the activity manager actually destroy the activity, it only called
public void onSaveInstanceState(Bundle savedInstanceState)
no
onStop
called, so no
noResume
will be called.
The correct to do this is, when put all states of this activity when
public void onSaveInstanceState(Bundle savedInstanceState)
called.
and in your onCreate() function, do such thing
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}
to check if you have some saved state.
Most code was copy from android developer site:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
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
}
}