public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
return;
}
// processing
}
Is it a good practice to avoid processing further if the savedInstanceState is not null?
does this have any drawback?
I expect this code is not what you want as there can be different times you want to have savedInstanceState so if it is set pull out the data you will have saved so the user has the same state though they may have rotated their phone.
You may want to look at this question and answers
What's onCreate(Bundle savedInstanceState)
Related
I have this following code:
public class MainActivity extends AppCompatActivity {
EditText edtInput;
private static final String STATE_RESULT = "state_result";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edtInput = (EditText) findViewById(R.id.edtInput);
}
#Override
protected void onSaveInstanceState(#NonNull Bundle outState) {
outState.putString(STATE_RESULT, edtInput.getText().toString());
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null){
edtInput.setText(savedInstanceState.get(STATE_RESULT).toString());
}
}
}
On Pixel 3 (running Android 12): type something in the EditText, then do a combo of screen rotations, turning on/off the screen, press back to home and open the app again. the user input is still on EditText
On Xiaomi Pocophone F1 (running Android 10) there's a slightly different behaviour: EditText is cleared if you press back and open the app again. but no problem as long as you only turn on/off or rotate the screen.
Not sure if I misunderstood Android activity lifecycle, or this is a bug on the OS. Any help is appreciated.
Before you can start figuring out why it's happening, you need to figure out what exactly is happening.
You should add some logging to see exactly where it fails. Maybe on the F1, the app gets killed before it calls onSaveInstanceState(). Or maybe onRestoreInstanceState() has savedInstanceState == null:
#Override
protected void onSaveInstanceState(#NonNull Bundle outState) {
outState.putString(STATE_RESULT, edtInput.getText().toString());
super.onSaveInstanceState(outState);
Log.d("***", "Saved")
}
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d("***", "Restoring: " + (savedInstanceState == null))
if (savedInstanceState != null){
edtInput.setText(savedInstanceState.get(STATE_RESULT).toString());
}
}
And then look at the logs to see what happens on the F1 when you exit the app using the back arrow, and then re-launch it.
Edit: Since it appears that onRestoreInstanceState() isn't being called on the F1, you should probably try to save your app state yourself, instead of relying on savedInstanceState. For example, you can just add an onTextChanged() listener to each of the editText fields, and save the text into SharedPreferences. And you can delete that preference when the user submits the text. You can then restore them in onCreate(). That way, you're completely independent of the lifecycle
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")));
}
I have an Activity with a Fragment inside.
In that fragment there are RecyclerView, and RecyclerViewAdapter.
In fragment's onCreate I'm doing this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TAGGG", "onCreate: ");
// Database handler
Contract.DbHelper dbHelper = new Contract.DbHelper(getContext());
dERecyclerViewAdapter.setEntries(dbHelper.readAllEntries());
}
Everytime the Activity is recreated(up navigation, rotation changes) data is being read again from the database.
What is the correct way to store it?
You can use the savedInstanceState to store the data through a bundle. You can store it like this
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Use the bundle to store data
}
And retrieve it like this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState!=null)
{
//Use the savedInstanceState to get the stored result
}
}
Hope this helps !
You should look at the CursorLoader class. Your situation is exactly what this class was intended for.
The loader itself can persist between configuration changes, so that when you call onCreate, if the loader has already performed the query it will just provide the data it already read rather than re-query the database.
See https://developer.android.com/guide/components/loaders.html
Also http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html
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.
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