onCreate being called on Activity A in up navigation - android

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

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");
}

Android change fragment of navigation view

I have an Android app with 1 base activity and a few fragments. They can be changed using the NavigationView inside the DrawerLayout. Users can change the language of the application in one of the fragments and when I relaunch the application, I want users to go back to that specific fragment.
=====DrawerLayout=====
1. Fragment Home -> This is the starting fragment
2. Fragment One
3. Fragment Settings -> Users change the language here.
When users change the language, a method in the base activity is called and I change the Locale, and call recreate(). This will refresh the app with the Fragment Home being displayed in the new language. I want to programatically change to Fragment Settings.
navigationView.<METHOD?>
In order to solve your problem, you can save the special state and recreate the activity. When the activity is recreated, it will know that it needs to move to the settings page using the saved state.
Try this in your activity:
static final String SHOW_SETTINGS = "SHOW_SETTINGS";
private boolean showSettings = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createLayoutAndDoOtherOnCreateThings();
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
if (savedInstanceState.getBoolean(SHOW_SETTINGS, false)) {
showSettingsFragment();
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(SHOW_SETTINGS, showSettings);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
private void callRecreateWithSettingsWhenRecreating() {
showSettings = true;
recreate();
}

Activity retain instance of Fragment on onSaveInstance

I'm writing an application where using onSaveInstance(..) to retain values on device config change(say device font, local).
Here application Activity using multiple Fragment to display. After chnage in config change when coming back to app then onCreate(..) execute and app checked if Bundle object is null. Now till this state app didn't set any Fragment child back but but still last set Fragment (before change in config) child started to execute it's life cycle method.
How can prevent it, one way to check Same Bundle object from Fragment child, same as Activity and return. But is there other way to remove child from Activity on device-config change!
Activity reference code to handle re-calling:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reading_activity);
if(savedInstanceState == null) {
init(savedInstanceState);
} else {
// Don't do anything
}
}
Here init(..) responsible to set Fragment child.

How to maintain the state of the activity?

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.

onBackPressed() behaviour with ActivityGroups

Quick question: I have an activitygroup. Within that Activitygroup I have an activity. If I press back while inside this activity. the onBackPressed method of the activity is called - Not the Activitygroups onBackPressed - Why is that ?
EDIT: Got my answer but the problem remains. Here follows code and explanation of my original issue:
I am using ActivityGroups within a TabHost and as such have been "forced" into overriding onBackPressed. I can navigate through my application without issue by pressing back on my phone and by pressing the tabs on my tabhost. But I cannot interact with the interface after pressing Back.
Once I press one of the tabs on the tabhost again I can interact with everything like normal. Why is this happening? Do I need to override onResume?
Relevant code
SettingsActivityGroup :
public class SettingsActivityGroup extends ActivityGroup
{
// Keep this in a static variable to make it accessible for all the nested activities, lets them manipulate the view
public static SettingsActivityGroup group;
// Need to keep track of the history if you want the back-button to work properly, don't use this if your activities requires a lot of memory.
private ArrayList<View> history;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Allocate history
this.history = new ArrayList<View>();
// Set group
group = this;
// Start root (first) activity
Intent myIntent = new Intent(this, SettingsActivity.class); // Change to the first activity of your ActivityGroup
myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
ReplaceView("SettingsActivity", myIntent);
}
/*
* Replace the activity with a new activity and add previous one to history
*/
public void ReplaceView(String pId, Intent pIntent)
{
Window window = getLocalActivityManager().startActivity(pId, pIntent);
View view = (window != null) ? window.getDecorView() : null;
// Add the old activity to the history
history.add(view);
// Set content view to new activity
setContentView(view);
}
/*
* Go back from previous activity or close application if there is no previous activity
*/
public void back()
{
if(history.size() > 1)
{
// Remove previous activity from history
history.remove(history.size()-1);
// Go to activity
View view = history.get(history.size() - 1);
Activity activity = (Activity) view.getContext();
// "Hack" used to determine when going back from a previous activity
// This is not necessary, if you don't need to redraw an activity when going back
activity.onWindowFocusChanged(true);
// Set content view to new activity
setContentView(view);
}
else
{
// Close the application
finish();
}
}
/*
* Overwrite the back button
*/
#Override
public void onBackPressed()
{
// Go one back, if the history is not empty
// If history is empty, close the application
SettingsActivityGroup.group.back();
return;
}
}
Arbitrary child of SettingsActivityGroup(CallForwardActivity)
public class CallForwardActivity extends ListActivity
{
....
#Override
public void onBackPressed()
{
// Go one back, if the history is not empty
// If history is empty, close the application
SettingsActivityGroup.group.back();
return;
}
}
Because I believe calling onBackPressed() of the currently selected activity is the desired behavior.
It's also worth noting that ActivityGroup is deprecated, but I assume you are coding for <3.0 and don't fancy working with the support libraries.
Regarding your edited question:
Another question on this site cites this article as a good ActivityGroup example, and I would agree http://ericharlow.blogspot.com/2010/09/experience-multiple-android-activities.html
This example just calls finish() on the current activity when back is pressed, and lets the os restart the previous activity, which is simpler than what you are doing, and will hopefully work! You can just call getParent() in your child activities too to avoid using that static reference (just seems easier to read to me that way!).

Categories

Resources