Store TextView on Button Click In onSaveInstanceState - android

I'm trying to save a TextView value that changes on a button click and keep it stored until I kill the app.
I am trying to use onSaveInstanceState and onRestoreInstanceState to save and restore as long as the app is running. It doesn't work for me. Here is my code.
TextView questionText;
Button button ;
String perso1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
perso1 = MainActivity.perso;
questionText = (TextView)findViewById(R.id.perso);
questionText.setText(perso1));
getSupportActionBar().setIcon(R.drawable.ic_back_icon);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.settings);
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
resetConsent();
questionText.setText("You clicked on the button");
}
});
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
String newtext = questionText.getText().toString();
outState.putString("TEXT", newtext);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);
questionText.setText(savedInstanceState.getString("TEXT"));
}
I'm trying to keep the new value of textview when I click on the button until I kill the app. What am I doing wrong?

ViewModel is what you need!
Why
The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations.
It makes your life easier. You don't need to think on how to save it in youe savedInstanceState, but you can just store the String in your ViewModel (as a LiveData), then observe it.
With LiveData, you can change the value everytime the button clicked, and observe the value everytime it changes.

You can always try to save state in a different way.
#Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
String newtext = questionText.getText().toString();
outState.putString("TEXT", newtext);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
//check if there was a previous saved state
if(savedInstanceState != null){
//get the value you stored earlier in onSaveInstanceState()
perso1 = savedInstanceState.getString("TEXT");
}
questionText = (TextView)findViewById(R.id.perso);
questionText.setText(perso1));
//....
}
But this is just another way to save state.
I think i your error is explained below.
//you did this correctly- look, you set questionText here
onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
//set the questionText below
questionText.setText(savedInstanceState.getString("TEXT"));
}
but then in onCreate() you set the questionText again. This time to an incorrect value.
perso1 = MainActivity.perso;//< -- setting perso1 to nothing?
questionText = (TextView)findViewById(R.id.perso);
questionText.setText(perso1));//<-- setting questionText again
onRestoreInstanceState
This method is called between onStart() and onPostCreate(Bundle).
In onSaveInstanceState() you did it correctly, in onRestoreInstanceState() you did it correctly, in onCreate() you set the value again to the wrong value.
Additionally read this when deciding to keep saving state this way or using a ViewModel
For simple data, the activity can use the onSaveInstanceState() method and restore its data from the bundle in onCreate(), but this approach is only suitable for small amounts of data that can be serialized then deserialized, not for potentially large amounts of data like a list of users or bitmaps.

Related

Button text gets reset on orientation change

In my android app, I am trying to solve an issue with orientation change.
I have a main layout where I have two buttons. On click of the first button (default text on this button is "Select a category"), a dialog box appears with a category list with categories displayed as radio buttons. After the user selects a category, the selected category name appears on the button. Now when I change the orientation in the emulator, the Button text gets reset again.
I have used onSaveInstanceState() like below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialization code
categoryList=(Button)findViewById(R.id.category_selection);
if (savedInstanceState != null)
{
System.out.println("savedInstanceState---
"+savedInstanceState.getString("bundle_category_name"));
categoryName=savedInstanceState.getString("bundle_category_name");
categoryList.setText(categoryName);
}
else
{
categoryList.setText(R.string.category);
}
// remaining code
}
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
// Save selected category name
System.out.println("saving category name "+categoryName);
outState.putString("bundle_category_name", categoryName);
}
I am able to get the category name back in onCreate(), the sysout prints correctly. But it is not getting set as the button text after change in orientation.
Please let me know if I am doing anything wrong.
Thanks
Add android:configChanges="orientation|screenSize" in your Android Manifest file.
<activity android:name="YourActivity"
...
android:configChanges="orientation|screenSize"
.../>
Saving and restoring the data works using two Activity lifecycle methods called onSaveInstanceState() and onRestoreInstanceState().
To save the state information override onSaveInstanceState() method and add key-value pairs to the Bundle object that is saved in the event that your activity is destroyed unexpectedly. This method gets called before onStop().
To recover your saved state from the Bundle override onRestoreInstanceState() method. This is called after onStart() and before onResume(). Check the below code
public class MainActivity extends Activity{
private static final String SELECTED_ITEM_POSITION = "ItemPosition";
private int mPosition;
#Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
// Save the state of item position
outState.putInt(SELECTED_ITEM_POSITION, mPosition);
}
#Override
protected void onRestoreInstanceState(final Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Read the state of item position
mPosition = savedInstanceState.gettInt(SELECTED_ITEM_POSITION);
}
}
#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.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "back to Android");
// etc.
}
To Retrieve the data
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}

int variable does not save with screen rotation

I put an imageview to load an image of a url, it is when I click on a button it passes to the next url, thus changing the image.
the problem is that when I rotate the screen it returns to the first image displayed.
I tried to do an if with incremented counter but it deletes the variable and returns to the first one again.
someone knows how to save the value of the "next" variable so when the screen rotates it keeps the value saved, or knows another way to keep the last image saved.
api picasso
code complete
private SmartImageView smartImage;
private Button btn;
private int proxima = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_redacao_nota_1000);
if (proxima == 0) {
smartImage = (SmartImageView) findViewById(R.id.meuSmartImage);
smartImage.setImageUrl("http://gabrielmartins70.000webhostapp.com/bao.png");
proxima++;
}
btn = (Button) findViewById(R.id.button18);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (proxima == 1) {
smartImage.setImageUrl("http://gabrielmartins70.000webhostapp.com/2.png");
}
}
});
}}
When your activity is recreated after it was previously destroyed, you can recover your saved state from the Bundle that the system passes your activity. Both the onCreate() and onRestoreInstanceState() callback methods receive the same Bundle that contains the instance state information.
Because the onCreate() method is called whether the system is creating a new instance of your activity or recreating a previous one, you must check whether the state Bundle is null before you attempt to read it. If it is null, then the system is creating a new instance of the activity, instead of restoring a previous one that was destroyed.
Save your int variable like following example does:
static final String STATE_USER = "user";
private String mUser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mUser = savedInstanceState.getString(STATE_USER);
} else {
// Probably initialize members with default values for a new instance
mUser = "NewUser";
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString(STATE_USER, mUser);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}

state of app after 2 rotations

i have been through this documentation regarding the topic save a state before the foreground activity will be destroyed...
and everything works really good now (after a device rotation), but when i rotate my device again after a rotation, i will loose my data again :(
here is my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MainActivity activity = this;
activity.setTitle("Cow Counter");
TextView QntyResultField = findViewById(R.id.textView);
QntyResultField.setText(Integer.toString(cowQnty));
}
// invoked when the activity may be temporarily destroyed, save the instance state here
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("qnty", cowQnty);
}
// How we retrieve the data after app crash...
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//cowQnty = savedInstanceState.getInt("qnty");
TextView QntyResultField = findViewById(R.id.textView);
QntyResultField.setText("Cows: "+Integer.toString(savedInstanceState.getInt("qnty")));
}
I think the solution will be maybe to implement a check if an instance state was already restored before...
i have tried then this here:
if(savedInstanceState.getInt("qnty") != 0){
TextView QntyResultField = findViewById(R.id.textView);
QntyResultField.setText("Cows: "+Integer.toString(savedInstanceState.getInt("qnty")));
}
buit then my inital part in my onCreate() method will write a zero in my result field
TextView QntyResultField = findViewById(R.id.textView);
QntyResultField.setText(Integer.toString(cowQnty));
Could anyone tell me if I am close to the solution?
You use a variable called cowQnty to store the value that is then saved in the bundle for your onSaveInstanceState as outState.putInt("qnty", cowQnty);, then when you restore it in onRestoreInstanceState you only set the TextView's value to the retrieved value and do not update the value for cowQnty.
How do you expect then to save an empty field again? There are two solutions to this;
Firstly, if cowQnty is not a sizeable amount and you do not mind using a tad of RAM, make cowQnty a static field and it will persist the data without needing to save it in a Bundle at all.
Secondly, just set cowQnty's value once again when you restore your state (why did you comment it out??), like so:
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
cowQnty = savedInstanceState.getInt("qnty");
TextView QntyResultField = findViewById(R.id.textView);
QntyResultField.setText("Cows: "+Integer.toString(savedInstanceState.getInt("qnty")));
}

Going back and forth between intents without losing user entered data

I have a form. Here, the user fills in details like event name, description, location etc. To select the location, I have set a button. This is my button code:
btnMap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent map = new Intent(getApplicationContext(), Map2.class);
startActivity(map);
}
});
I select the location from there, and the data is passed back to my main intent correctly. But the thing is, the data in the other fields like event, description etc. that users filled in are lost.
I tried startActivityForResult(map,1); too. Doesn't work. Is there a way to keep the data, without sending them in a bundle to the other intent and getting them back? like the select image button does? It goes to the gallery and comes back without resetting the other fields
contactImageImgView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Image"), 1);
}
});
You need to save your activity state.
Override the method onSaveInstanceState and persist all your data in the bundle
In onCreate, if savedInstanceState is not null, restore all your data and set all the fields.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("MY_FIELD", 43);
// ... other fields
super.onSaveInstanceState(savedInstanceState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
if (savedInstanceState != null) {
int value = savedInstanceState.getInt("MY_FIELD");
// ... update your views
} else {
// no previous state, start fresh
}
}
Details here
Note: you have mentioned that rotation is blocked. This is generally bad for the user unless it's part of the feature of the app.
Explanation:
A screen rotation is a configuration change that causes the activity to restart with the appropriate resources. There are many more configuration changes such as screen unlock,device docked etc. Not all of them trigger an activity restart but some do. When your activity restarts due to a configuration change, onSaveInstanceState gets called and savedInstanceState will be not-null when onCreate is called.
When you start a new activity Android may destroy the previous one to recover some of the resources it was consuming. In that case, when you return to that previous activity, it is actually a new instance of the Activity subclass and the internal state has been lost. It's up to you to save and restore any state necessary within the onSaveInstanceState and onCreate callback methods, respectively.
Have a look at this page for more information and examples: Recreating an Activity | Android Developers
public class FormActivity extends Activity {
private static final String NAME = "NAME";
private EditText nameEdit;
// Declare other view references here...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_form);
nameEdit = (EditText) findViewById(R.id.name_edit);
// Find other views...
if (savedInstanceState != null) {
final String nameValue = savedInstanceState.getString(NAME, "");
nameEdit.setText(nameValue);
// Restore other saved values...
} else {
// No saved values to restore
}
}
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
final String nameValue = nameEdit.getText().toString()
outState.putString(NAME, nameValue);
// Put (save) other values into the outState bundle...
super.onSaveInstanceState(outState, outPersistentState);
}
// Other FormActivity code...
}

edit text saving status in android

i did a lot of trials before coming here, i need that user find the same values entered in
an activity when he returns to , i did this code but it is not working :
public class ActivityUn extends Activity {
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString("arm_1", rm_1ts);
savedInstanceState.putString("arm_2", rm_2ts);
super.onSaveInstanceState(savedInstanceState);
}
public void ajouter(View v) {
db.open();
long id = db.insertMENAGE(rm_1ts,rm_2ts); }
EditText rm_1;
EditText rm_2;
String rm_1ts = "";
String rm_2ts = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_un);
rm_1 = (EditText)findViewById(R.id.rm_1);
rm_2 = (EditText)findViewById(R.id.rm_2);
if (savedInstanceState != null) {
// Restore value of members from saved state
rm_1ts = savedInstanceState.getString("arm_1");
rm_2ts = savedInstanceState.getString("arm_2");
rm_1.setText(rm_1ts);
rm_2.setText(rm_2ts);
}
Button bton = (Button)findViewById(R.id.ajoutUn);
bton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rm_1ts = rm_1.getText().toString();
rm_2ts = rm_2.getText().toString();
ajouter(v);
}
});
The problem is that onSaveInstanceState is only called when your Activity is killed via System to free memory or a 3rd party app. But when you press a back button in an Activity it simply is equivalent to finish(). In this case onSaveInstanceState is not called. So if you want to store data every time your Activity is created just store the values in a SharedPreference. You can store the values either in onStop or onPause method depending on your needs.
Here you can learn more about SharedPrefence and other types of storage options.
For the sake of simplicity, you could store the value in the SharedPreferences.
getSharedPreferences().edit().putString("myEditText", yourValue).commit();
That's it.
Try restoring the state in onStart or onResume instead of onCreate. onCreate is only called if the activity needs to be recreated after it is destroyed. Often the activity will be retained in the background in a stopped state, and won't call onCreate when it comes back.
Anywhere in your file, put:
#Override
public void onResume() {
super.onResume();
//Your code here
}

Categories

Resources