How to maintain the state of the activity? - android

I am trying to save the state of the activity in android.Basic scenario is there is 2 activities A and B.Activity A contains 2 edittext fields.User enters some value into it and moves to activity B via intent.When user comes back to Activity A (by intent i have provided a back button) I need to display those values in the 2 edittext fields that the user had entered (i.e maintain the state of activity A).Also i do not want to use shared preferences or make those fields as static.
I have used the following code but it does not help:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.manual_entry);
edittext1=(Edittext)findViewById(R.id.edittext1);
}
#Override
protected void onSaveInstanceState(Bundle savedInstanceState)
{
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("cardvalue_saved_inst", value_card_manuallyentered);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
value_savedinstance = savedInstanceState.getString("cardvalue_saved_inst");
Log.e("value_savedinstance",""+value_savedinstance);
edittext1.setText(value_savedinstance);
}

In ActivityA, if you launch ActivityB and don't call finish() on yourself, when ActivityB finishes (when user presses BACK button or otherwise), ActivityA will be shown in the same state that it was in. This is just standard Android behaviour and you don't need to do anything special.
onRestoreInstanceState() is not called if a paused activity gets resumed (which is the usual case where ActivityA launches ActivityB and ActivityB then finishes).
onRestoreInstanceState() is only called if Android killed your activity (during orientation change for example) or killed your process. In that case, when the user returns to your activity, Android will create a new instance of the activity and then call onRestoreInstanceState().

I had to simply call finish() in Activity B and it worked.

Related

How can we backstack activities when back button is pressed ? i.e Pop up activities from the stack

Simply , When activity 'B' is stacked after activity 'A'.Want activity 'A' to resume while back button is pressed in activity 'B'. Don't want activity'A' to restart using intent , want to resume activity 'A'.
You can influence this behaviour using various launchmode flags. See the official documentation about this topic:
https://developer.android.com/guide/components/activities/tasks-and-back-stack
You can override onSaveInstanceState(Bundle savedInstanceState) and write the application state values which you want to save as a 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.putBoolean("X", true);
savedInstanceState.putString("Y", "Sultan");
// etc.
}
The Bundle 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.
int x = savedInstanceState.getInt("X");
String y = savedInstanceState.getString("Y");
}

Override onSavedInstanceState: savedInstanceState object is always null

I have two activities (A and B). Activity A calls activity B. Activity B has Back (Up) button like this:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Now when this UP button is pressed, onCreate of activity A is again called. In the activity A, there is a classId variable (which I got from an Intent) which I want to retain. For this I have following code in my onCreate of activity A:
if (savedInstanceState == null)
{
Intent intent = getIntent();
classId = intent.getIntExtra("CLASS_ID", 0);
}
else
{
classId = savedInstanceState.getInt("CLASS_ID");
}
I have also overriden the onSavedInstanceState method:
#Override
protected void onSaveInstanceState(Bundle savedInstanceState)
{
savedInstanceState.putInt("CLASS_ID", classId);
super.onSaveInstanceState(savedInstanceState);
}
I am following this SO answer:
onCreate being called on Activity A in up navigation
The problem I am facing is that when I come again to activity A by passing back button in activity B, onCreate gets called and I found savedInstanceState to be NULL.
Edit:
Is there any other way to save my classId variable so that when I return again to activity A, I can use that?
Edit 2
If I set launch mode of my activity A to SingleTop in the manifest file, my issue gets resolved. Is it the right approach?
You should not suppose that onSaveInstanceState called each time you go to next activity.See the docs
This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state. For example, if activity B is launched in front of activity A, and at some point activity A is killed to reclaim resources, activity A will have a chance to save the current state of its user interface via this method so that when the user returns to activity A, the state of the user interface can be restored via onCreate(Bundle) or onRestoreInstanceState(Bundle).
You may further consult with official docs here
Try this
public class SingletonHolder {
//your id here as what data type you want
private static SingletonHolder instance;
public static SingletonHolder getInstance() {
if (instance == null) {
instance = new SingletonHolder();
}
return instance;
}
//set getter setter here
}
If not successfull feel free to comment
I changed the launchMode of the activity A to singleTop in the mainfest file like this:
android:launchMode="singleTop"
I followed this question on SO: Setting launchMode="singleTask" vs setting activity launchMode="singleTop"
By using this approach, activity A is not destroyed and when I just finish the activity B or click UP navigation in activity B, the existing instance of activity A is launched again.

why isn't my activity class's instance variable value being preserved onResume()?

I have a listview in Activity B populated by a list of lists through an adapter. This list of lists was retrieved from a bundle passed by Activity A like so:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_results);
lvLineups = (ListView)findViewById(R.id.lvResults);
}
#Override
protected void onResume() {
super.onResume();
lineups = (ArrayList<ArrayList<Band>>) getIntent().getSerializableExtra("results");
ResultsAdapter resultsAdapter = new ResultsAdapter(this, lineups);
lvLineups.setAdapter(resultsAdapter);
}
I launch an implicit video intent from this activity so Activity B goes in the background(paused, onPause invoked) and the video goes in the front.
I click back on the video, killing that activity.
Activity B's resumes(onResume is called) and I see that the list of lists(lineups) is now empty. According to the activity lifecyle, this activity is resuming so why don't I still see the list of lists in step 1, and how do I preserve it after the implicit video intent.
Note: This looks like a vertical listview where each row is a horizontally scrolling list. I've gotten this layout to work except when adding the video intent. Playing a video and scrolling down causes an indexoutofbounds exception because lineups, the bundle received from Activity A, is now gone.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_results);
lvLineups = (ListView)findViewById(R.id.lvResults);
lineups = (ArrayList<ArrayList<Band>>) getIntent().getSerializableExtra("results");
ResultsAdapter resultsAdapter = new ResultsAdapter(this, lineups);
lvLineups.setAdapter(resultsAdapter);
}
after the media player plays the video and closes, returning to Activity B, I see in the debugger that lineups is empty. This is strange because it is an uninitialized instance variable before onCreate is called. I expected it to remain the same after the video intent is launched from Activity B, or at least be null.
OK, Let us go through the activity cycle.
Initially you started Activity B from Activity A => So the lineups is fetched from the bundle of activity A. So you get that value.
Then you launched the Video which is another intent. Then you are going back. At this point the onResume() gets called again (Where the bundle has no value for lineups). You should get the lineups in onCreate() rather than onResume() which gets called after a pause.

Android Save Instance State

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.

onCreate being called on Activity A in up navigation

So I have an Activity A and an Activity B. I want Activity A to be able to navigate to Activity B with the press of a button. That works, but when I use the up navigation(the home button in the action bar) to navigate back to Activity A, onCreate() is called again and the old information that the user typed in is lost.
I've seen: onCreate always called if navigating back with intent, but they used Fragments, and I'm hoping not to have to redesign the entire app to use fragments. Is there any way I can stop onCreate() from being called every time Activity A becomes active again?
This behavior is totally fine and wanted.
The system might decide to stop Activities which are in background to free some memory.
The same thing happens, when e.g. rotating the device.
Normally you save your instance state (like entered text and stuff) to a bundle and fetch these values from the bundle when the Activity is recreated.
Here is some standard code I use:
private EditText mSomeUserInput;
private int mSomeExampleField;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO inflate layout and stuff
mSomeUserInput = (EditText) findViewById(R.id.some_view_id);
if (savedInstanceState == null) {
// TODO instanciate default values
mSomeExampleField = 42;
} else {
// TODO read instance state from savedInstanceState
// and set values to views and private fields
mSomeUserInput.setText(savedInstanceState.getString("mSomeUserInput"));
mSomeExampleField = savedInstanceState.getInt("mSomeExampleField");
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// TODO save your instance to outState
outState.putString("mSomeUserInput", mSomeUserInput.getText().toString());
outState.putInt("mSomeExampleField", mSomeExampleField);
}
You can make the up button behave like pressing back, by overriding onSupportNavigateUp()
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
If you want to navigate from child to parent without recreating the parent (calling onCreate method), you may set the android:launchMode="singleTop" attribute for the parent activity in your AndroidManifest.xml

Categories

Resources