How to use onSavedInstance? - java

One quick question:
Why does my onSavedInstance not work? I want to save last state of user activity (current workout session etc.) but in some particular reason it keeps turning me back to the mainActivity when I press the home or overview button and then I return to the application. It should return me the last saved state of activity but something seems to be bugged. I have been struggling with this problem for two weeks. I searched all over the forum but I still can’t find the answer. Hope someone can help:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_workout);
if (savedInstanceState != null) {
// What should I call here?
} else {
// And here?
}
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
}

onSaveInstanceState(Bundle savedInstanceState) is called when the user leaves your app.It provides a Bundle object that you can pass values you want to save as key value pairs.
static final String WORKOUT_STATE = "state";
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current workout state
savedInstanceState.putInt(WORKOUT_STATE, currentState);
super.onSaveInstanceState(savedInstanceState);
}
There are two options for where you can restore the current state when the activity is recreated. It can be done in onCreate(Bundle savedInstanceState) method or onRestoreInstanceState(Bundle savedInstanceState). If you should do it in onCreate, you should check if the savedInstanceState is not null.
If savedInstanceState is not null then the activity is being recreated and this is where you extract the values.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
currentState = savedInstanceState.getInt(WORKOUT_STATE);
} else {
// Initialize members with default values for a new instance
}
}
Instead of extracting the values in the onCreate method, you can optionally use the onRestoreInstanceState(Bundle savedInstanceState) method. This method is called if there is a state to restore so you don't need to check if savedInstanceState is null.
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore state
currentScore = savedInstanceState.getInt(WORKOUT_STATE);
}
You can read more about saving UI states here: https://developer.android.com/topic/libraries/architecture/saving-states.html

SOLVED!
I fixed my problem,
believe it or not the problem was in FLAG_ACTIVITY_NO_HISTORY in my intent service. Thanks for trying to help!

Related

Preserving Value When Orientation Changes

I am developing a very basic Android App that adds a number in TextView whenever I hit the Button. The digit showing in TextView is also preserved when the orientation of the Mobile changes using the onSaveInstanceState() and onRestoreInstanceState() functions.
The problem is when orientation changes the value is preserved but when the Button is pressed once again after the changing of the orientation it again starts the counting from 0 rather then starting it from the preserved value.
My code:
public class MainActivity extends AppCompatActivity {
TextView showValue;
int counter=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showValue = (TextView) findViewById(R.id.CounterValue);
}
public void countIN(View view)
{
counter++;
showValue.setText(Integer.toString(counter));
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("my_text", showValue.getText().toString());
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
showValue.setText(savedInstanceState.getString("my_text"));
}
}
Thank You for your response.
add
counter=Integer.parseInt(savedInstanceState.getString("my_text"));
inside onRestoreInstanceState method
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
showValue.setText(savedInstanceState.getString("my_text"));
counter=Integer.parseInt(savedInstanceState.getString("my_text"));
}
You can save and get data using several methods
First If your data is small, then you can use onSavedInstanceState and onRestoreInstanceState .. for details follow this answer or this one
Second if you have too much data to store, then use ViewModel instead; this is a tutorial that you can start from.

Setting EditText in Bundle test not working

Hi I am practicing how Bundle savedInstanceState works in Activity creation and it restoration. I have tried this:
private EditText mTextBox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextBox = (EditText) findViewById(R.id.etName);
mTextBox.setText("hello");
if(savedInstanceState != null){
Toast.makeText(this, savedInstanceState.getString("name"),
Toast.LENGTH_SHORT).show();
mTextBox.setText(savedInstanceState.geteString("name"));
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("name", "Joe");
super.onSaveInstanceState(outState);
}
On first onCreate() obviously this will set the EditText field with "hello" as savedInstanceState is null the if block will not be executed. When I change the orientation the Activity goes through all callbacks and Toast the String in the if block, however, it does not set the mTextBox with value from Bundle passed in. The EditText is still set to hello instead of Joe, however, the Toast in if block shows Joe.
Can anyone point out why this is not working as my expectation?
Thanks
This is happening as a result of TextView.getFreezesText, which will:
Return whether this text view is including its entire text contents in
frozen icicles. For EditText it always returns true.
And some more info from TextView.setFreezesText:
Control whether this text view saves its entire text contents when
freezing to an icicle, in addition to dynamic state such as cursor
position. By default this is false, not saving the text. Set to true
if the text in the text view is not being saved somewhere else in
persistent storage (such as in a content provider) so that if the view
is later thawed the user will not lose their data. For EditText it is
always enabled, regardless of the value of the attribute.
icicles is referring to savedInstanceState, that's just what it used to be called.
If you'd like to save and restore the text yourself, you could create a custom EditText and override getFreezesText, something like:
public class NonFreezingEditText extends AppCompatEditText {
public NonFreezingEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean getFreezesText() {
return false;
}
}
You could also use View.post:
mTextBox.post(() -> mTextBox.setText(savedInstanceState.getString("name")));
or Activity.onRestoreInstanceState
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mTextBox.setText(savedInstanceState.getString("name"));
}
You need setText different "hello". see example
private EditText mTextBox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextBox = (EditText) findViewById(R.id.etName);
mTextBox.setText("hello");
if(savedInstanceState != null){
Toast.makeText(this, savedInstanceState.getString("name"),
Toast.LENGTH_SHORT).show();
mTextBox.setText(savedInstanceState.getString("name"));
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
mTextBox.setText("Joe");
outState.putString("name", mTextBox.getText().toString());
super.onSaveInstanceState(outState);
}
OR you must override onRestoreInstanceState. Not call onCreate when text not change.
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if(savedInstanceState != null){
mTextBox.setText(savedInstanceState.getString("name"));
}
}

Fragment become null

I am developing Android application and i have in my Main activity a fragment with this:
searchInnerPlaylistFragment = InnerPlaylistFragment.newInstance();
Bundle bdl = new Bundle();
bdl.putString(InnerPlaylistFragment.PLAYLIST_ID_KEY, ytf.getId());
bdl.putString(InnerPlaylistFragment.PLAYLIST_TITLE_KEY, ytf.getTitle());
bdl.putInt(InnerPlaylistFragment.PLAYLIST_VIDEO_NUMBER_KEY, videoNum);
searchInnerPlaylistFragment.setArguments(bdl);
ft.replace(R.id.search_inner_list_fragment, searchInnerPlaylistFragment).commit();
And when i open the "Don't keep activities" option in the developer Options, and go to background with my app and return to the app the searchInnerPlaylistFragment become null but it's still in the activity.
There is an option to save this fragment?
To correctly save instance state of Fragment, you should do following codes:
In the fragment, save instance state by override onSaveInstanceState and restore on onActivityCreated:
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
if (savedInstanceState != null) {
//Restore the fragment's state here
}
}
...
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Save the fragment's state here
}
And important point, in the activity, you have to save fragment's instance on onSaveInstanceState and restore on onCreate.
public void onCreate(Bundle savedInstanceState) {
...
if (savedInstanceState != null) {
//Restore the fragment's instance
mContent = getSupportFragmentManager().getFragment(
savedInstanceState, "mContent");
...
}
...
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Save the fragment's instance
getSupportFragmentManager().putFragment(outState, "mContent", mContent);
}
Hope this help.
You can put your fragment on backStack, so that when you press back or navigate to back screen you can get it back from stack
change your fragment replacing line as
ft.replace(R.id.search_inner_list_fragment, searchInnerPlaylistFragment).addToBackStack().commit();
and when you want to get this fragment back you can pop it like
manager.popBackStack();

TextView doesn't show the required text

My MainActivity class has an if that checks is something is true it starts a new Activity which sets the text of a TextView to what I want.
MainActivity:
public static int caseA = 1;
if(caseA) {
Intent i = new Intent(Timer.this, WorkTimerNotification.class);
startActivity(i);
}
then it goes to the new Activity and it should check the value of caseA.
WorkTimerNotification:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_work_timer_notification);
TextView timerMetric = (TextView)findViewById(R.id.tester_texter);
if(MainActivity.caseA) {
timerMetric.setText("min");
}
Problem: It does not change the text. Also, lets say I have many other if statements in mainactivity like:
if(caseB) {}
if(caseC) {}
//and so on..
How would I perform the checks? More importantly, how do I get this caseA check to work though.
You need to call findViewById() in onCreate():
private TextView timerMetric;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_work_timer_notification);
timerMetric = (TextView)findViewById(R.id.tester_texter);
if(caseA) {
timerMetric.setText("min");
}
}
Right now you are calling it before calling setContentView(), before the view hierarchy is generated. For this reason, your code fails.

whats wrong with this code? it always returns savedInstanceState as null

This code always returns savedInstanceState as null
public class DemoidActivity extends Activity implements OnClickListener, android.view.View.OnClickListener {
EditText t1=null;
EditText t2=null;
EditText t3=null;
EditText t4=null;
String data1 = null,data2=null,data3=null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t1=(EditText)findViewById(R.id.editText1);
t2=(EditText)findViewById(R.id.editText2);
t3=(EditText)findViewById(R.id.editText3);
t4=(EditText)findViewById(R.id.editText4);
Button b1=(Button)findViewById(R.id.button1);
Button b2=(Button)findViewById(R.id.button2);
b1.setOnClickListener(this);
b2.setOnClickListener(this);
}
Their is nothing wrong with the code as such. The reason why you are getting the savedInstanceState as null in your onCreate() method is because your activity is created for the first time and so there won't be any saved state as such.
It will only be set if you implement the method onSaveInstanceState().
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
It means that your activity's state is never saved.
Try to override the onSaveInstanceState() method:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Put your stuff in the bundle
}
Then use it to retrieve data/activity sate whether in the onCreate() method or in the onRestoreInstanceState() one:
if (savedInstanceState != null) {
//Retrieve data
}

Categories