using onResume and onPause - android

Suppose I have two activities, activity1 and activity2.
I want to navigate from activity1 to activity2, get some info from activity2 and insert back it to activity1 and also I don't want to lose activity1 previous state as I left.
how can I save its state ?

what you are describing is the perfect classic reason to use the Activity.startActivityForResult() method.
this what google wrote in this method documentation:
Launch an activity for which you would like a result when it finished. When this activity exits, your onActivityResult() method will be called with the given requestCode
so what you should do is: from your activity1 start activity for result, and from activity2 use the setResult(int resultCode, Intent data) method with the data you want your activity1 to get back, and call finish() (it will get back to onActivityResult() in the same state activity1 was before..).

Override onSaveInstanceState(Bundle) in activity1 to save whatever data you want then override onRestoreInstanceState(Bundle) in the same activity to get the values back. Using Bundle, you can store pretty much any data that you want. I'd recommend something like this:
public class MainActivity extends Activity {
...
public static final String DATA1_KEY = "data1";
private boolean value1;
...
#Override
protected void onSaveInstanceState (Bundle outState) {
outState.putBoolean(DATA1_KEY, value1);
}
#Override
protected void onRestoreInstanceState (Bundle savedInstanceState) {
value1 = savedInstanceState.getBoolean(DATA1_KEY);
}
}

You should override onSaveInstanceState(Bundle savedInstanceState)
Please check this answer for example code
Or use SharedPreferences. Check this code

If you want to keep your data alive only at runtime, the consider using static members. Then you can access and manipulate these members from any activites. for example:
public class FirstActivity extends Activity
{
public static String data = null;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(...);
data = "This is a test!";
}
}
From your second activity you can access these static variables like
public class SecondActivity extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(...);
if(FirstActivity.data!=null)
{
//You can use it:
System.out.println(FirstActivity.data);
}
}
}
Of course you can add getter/setter functions to make it safer and more elegant.
If you want to store them for a longer time, the please consider using:
SharedPreferences
SQLite
or store your data in an online database.

The user performs an action in your app that starts a new activity. The current activity is stopped when the second activity is created. If the user then presses the Back button, the first activity is restarted.
When your activity is stopped, the Activity object is kept resident in memory and is recalled when the activity resumes. You don’t need to re-initialize components that were created during any of the callback methods leading up to the Resumed state. The system also keeps track of the current state for each View in the layout, so if the user entered text into an EditText widget, that content is retained so you don't need to save and restore it.
Note: Even if the system destroys your activity while it's stopped, it still retains the state of the View objects (such as text in an EditText) in a Bundle (a blob of key-value pairs) and restores them if the user navigates back to the same instance of the activity.
CommonsWare here says:
When user "press the BACK button", then the Bundle from
onSaveInstanceState() (if any) is discarded, as the user has indicated
they are finished with the activity. The onSaveInstanceState() Bundle
is used in cases where the user has not said they are finished with
the activity (e.g., they accepted an incoming phone call) yet Android
elects to destroy the activity to free up RAM.
And documentation says:
Note that it is important to save persistent data in onPause() instead
of onSaveInstanceState(Bundle) because the later is not part of the
lifecycle callbacks, so will not be called in every situation as
described in its documentation.
In other words, put your save/restore code for non View objects in onPause() and onResume() instead of onSaveInstanceState(Bundle) and onRestoreInstanceState(Bundle).Finally I guess that you don't need to save any state if you only have View objects and if you have any other states you can use preferences,file or sqlite to save them in onPause() and retreive them in onResume().
You can see more details in these pages:
Stopping and Restarting an Activity
Saving Activity state in Android
Android wont save the current state of an activity

Related

onRestoreInstanceState is not being called on Back button pressed

I'm trying to save and restore application state as savedInstanceState.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt(STATE_Tracker, 1);
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int value = savedInstanceState.getInt(STATE_Tracker);
if (value==1){
}
else {
}
}
That code works when home button pressed. But if I press back button, and run the app again, its not working.
Any help?
From developers guide:
When your activity is destroyed because the user presses Back or the activity finishes itself, the system's concept of that Activity instance is gone forever because the behavior indicates the activity is no longer needed. However, if the system destroys the activity due to system constraints (rather than normal app behavior), then although the actual Activity instance is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed. The saved data that the system uses to restore the previous state is called the "instance state" and is a collection of key-value pairs stored in a Bundle object.
In other words, when you press the back button, you will not have restore behavior the lifecycle of the activity is considered completed and no longer needed, thus you don't need to restore the instance state.
If you do need however you could override
#Override
public void onBackPressed() {
super.onBackPressed();
}
And persist the state in any storage option like SharedPreference.

Dealing with SavedInstances, and restoration of activity

basically my app has 2 activities.Say "A" and "B"
.
A launches B.
Activity B plays music and also has a notification.
Case 1:when the view is still on activity B` i press home button and then i click on the the notification, activity B is opened with its view intact and with its music playing (because in the manifest i am using android:launchMode= "singleTop" and hence another instance of the activity is not created) this part is as desired......
but
Case 2:when the view is on activity B and i press back button ,activity A appears and then i click on the the notification, activity B is opened with the view lost and music also stops(not desired)......i am making a guess that it happens because when i press the back button the activity is destroyed ,so i have to progamatically restore its view right??so to restore its view i override two methods .....
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("boolMusicPlaying", boolMusicPlaying);
savedInstanceState.putInt("swapnumber", swapnumber);
savedInstanceState.putString("seekbarprogress", progress2);
savedInstanceState.putInt("position.seekbar",seekbar.getProgress());
savedInstanceState.putString("seekmaxString", max2);
savedInstanceState.putInt("seekmaxInt",seekMax);
savedInstanceState.putParcelableArrayList("songfetails",songdetails);
super.onSaveInstanceState(savedInstanceState);
}
//make a note ....even if i don't override onDestroy() and don't call on SaveInstanceState explicitly, then too i am not getting any desired effect.......
#Override
public void onDestroy()
{ Bundle savedState = new Bundle();
onSaveInstanceState(savedState);//because of this line....the app is crashing......
super.onDestroy();
}
but it didn't help.....
and in on create i am putting a check if saved instances is null or not....create view accordingly...(i.e from saved instances or from fresh) but it didn't help...
also this line is giving a crash ...onSaveInstanceState(savedState);
even if i don't override ondestroy() and kill the app manually from task killer,and then try to open activity B,then too the saved instances thing should work right,because the method OnSaveInstanceState will be automatically called then,right???please help
Basically if you have pressed a back button,restoration of activity should be done using shared preferences/or a database but if you haven't pressed the back button and then you want to restore the state of the activity (because the activity was destroyed by the system ) then the bundle savedinstances can be used ...
From Android documentation:
When your activity is destroyed because the user presses Back or the activity finishes itself, the system's concept of that Activity instance is gone forever because the behavior indicates the activity is no longer needed. However, if the system destroys the activity due to system constraints (rather than normal app behavior), then although the actual Activity instance is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed. The saved data that the system uses to restore the previous state is called the "instance state" and is a collection of key-value pairs stored in a Bundle object.
To fix second problem you must restore data form some other source (service that plays music, restore info from application context or singleton, etc.)
For more info check this.

Activity lifecycle and class properties

Any activity can be killed under certain circumstances (e.g. "Other applications need memory"). After this, onCreate is called again on the activity.
The documentation says that in this case the "process is killed". Does this mean that the whole Activity instance is gc'ed and constructed again or only the GUI parts?
Given:
public class MyActivity extends Activity
{
private SomeClass someProperty = null;
#Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate (savedInstanceState);
if (someProperty == null) someProperty = new SomeClass ();
Log.d ("X", someProperty.toString () );
}
}
Will someProperty be null after the activity is killed and comes again to front, or will someProperty still be the same?
I am asking this, as it is hard to emulate the condition "Other applications need memory".
If you do nothing in onSaveInstanceState() method, it will be null. You might find some infomation useful reading this Android developer guide about activity lifecycle.
If you want the someProperty to be saved when the Activity is not destroyed normally(i.e., the user press the BACK button or the app calls finish() ), you can override the onSavedInstanceState() method and save whatever you want. There is a more explicit example in the tutorial linked above.
Also, there is another article and yet another article that explain the lifecycle of activity quite clear.
Hope helpful.
EDIT:
About when the onSavedInstanceState() will not be called(i.e. "destroy normally", which might be a confusing expression), this article says and I quote:
If the user interacts with an activity and presses the Back button or if the finish() method of an activity is called, the activity is removed from the current activity stack and recycled. In this case there is no instance state to save and the onSaveInstanceState() method is not called.
If the user interacts with an activity and presses the Home button, the activity instance state must be saved. The onSaveInstanceState() method is called. If the user restarts the application it will resume or restart the last running activity. If it restarts the activity it provides the bundle with the save data to the onRestoreInstanceState() and onCreate() methods.

A finished Activity re-created after a coincident orientation change

I don't know if this behavior is normal because I suppose a call to finish() would stop the activity from being re-created.
Here is an excerpt of the activity class:
public class MyActivity extends FragmentActivity {
private RetainFragment retainFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
......
retainFragment = getSupportFragmentManager().findFragmentByTag("RetainFragment");
if(retainFragment == null) {
retainFragment = new RetainFragment();
getSupportFragmentManager().beginTransaction().add(retainFragment, "RetainFragment").commitAllowingStateLoss();
}
if(retainFragment.isFinish) {
Log.v("MyActivity", "isFinish == true");
this.finish();
}
}
// a on-click event handler for a finish button
public void onFinishClicked(View view) {
retainFragment.isFinish = true;
this.finish();
}
private class RetainFragment extends Fragment {
private boolean isFinish = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRetainInstance(true);
}
}
}
The activity is persistent(I store the other persistent variables in the RetainFragment too but I didn't show them) and is closed only after the user has clicked the finish button, at which point onFinishClicked(View) would be called, and the activity should be finished by the system. I don't anticipate it to be recreated by the system after a coincident screen rotation. This happens rarely and I handle it by calling finish() again within the onCreate() method. However, it looks pretty ugly here because a finished activity is supposed to be dead forever and now I have to explicitly handle it. :(
Is there any misunderstanding of the activity lifecycle or the retain fragment on my part?
If you work on Android, whenever you hear yourself saying "this Activity will be closed only after X". Don't. You should never rely on an Activity having a highly-controlled lifecycle. Your Activity should be designed in such a way that no matter when it is destroyed and recreated, it just works.
To retain information across rotations and so on, add code to onSaveInstanceBundle and then check for it on your onCreate and pull out the saved values.
This is a standard Android behavior. Take a look at this paragraph of Android documentation.
Unless you specify otherwise, a configuration change (such as a change in screen orientation, language, input devices, etc) will cause your current activity to be destroyed, going through the normal activity lifecycle process of onPause(), onStop(), and onDestroy() as appropriate. If the activity had been in the foreground or visible to the user, once onDestroy() is called in that instance then a new instance of the activity will be created, with whatever savedInstanceState the previous instance had generated from onSaveInstanceState(Bundle).
To avoid this, you can set android:configChanges attribute in its manifest. For any types of configuration changes you say that you handle there, you will receive a call to your current activity's onConfigurationChanged(Configuration) method instead of being restarted. If a configuration change involves any that you do not handle, however, the activity will still be restarted and onConfigurationChanged(Configuration) will not be called.
I was encountering the same exact problem. That is, I had an Activity A that would start an Activity B using startActivityForResult. B's orientation is locked by the manifest. A's orientation is not locked.
When I rotated my device so the orientation was different, Activity B would not be recreated. This is expected and normal. However, once I performed a UI action that would finish() Activity B, instead of seeing Activity A being reconstructed and shown on the screen, I was shown Activity B again. Additionally, Activity's B's onActivityResult was being called instead of A's onActivityResult.
I figured out what was happening. I was using the same Intent object used to launch A to also launch B. After the orientation change and after B is finished, the Android system detects that Activity A needs to be rebuilt, since A was last built when the orientation was different. The system will reconstruct A using the same Intent object initially used to build A. However, the Intent object was modified to launch B instead, so the system will reconstruct Activity B instead of Activity A.
My code followed logic similar to below:
public class A extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...omitted code for clarity...
Intent i = getIntent();
i.setClass(this, B.class);
startActivityForResult(i, 0);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//...omitted code for clarity...
}
}
And my Activity B looked like:
public class B extends Activity {
//...omitted code for clarity....
public void myFinishingClickHandler(View clickedView) {
//...omitted code for clarity...
finish();
}
}
Quick walkthrough of the scenario:
Device is in portrait mode. User launches Activity A. System will construct Activity A with an Intent I, whose target is set to A.
Activity A modifies its Intent I by changing the target to B.
Activity A starts an activity with Intent I. The system will construct Activity B since I is now pointing to B.
B is now running. User changes the device orientation to landscape.
User clicks button whose click listener calls myFinishingClickHandler. The method calls finish() on Activity B.
Activity B finishes. The system begins the process of restoring Activity A.
The system notes that Activity A was constructed when the device was in portrait orientation, but now the device is in landscape mode. The system will try recreating Activity A instead. The existing Activity A is sent through its destruction flow (calling onDestroy).
The system will reconstruct Activity A using the saved Intent I. However, I's target is still Activity B. The system instead builds Activity B instead of Activity A.
Solution: Don't share Intents for launching activities. Use the Intent copy constructor.
Also, lock your activities' orientations to worry less about orientation changes (other configuration changes will cause your activities to be reconstructed, e.g. changing languages).

when is onRestoreInstanceState called?

Sorry for my incomprehension, but I am new in the android development.
I have an application with activity A and activity B in it, and I go from activity A to activity B. When I left activity A, the onSaveInstanceState method was called, but when I went back to activity A (from activity B in the same application), the bundle in the onCreate method was null.
What can I do, to save the activity A's previous state? I only want to store the data for the application lifetime.
Can someone help me with this?
Here is my code for Activity A:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null)
{
Log.v("Main", savedInstanceState.getString("test"));
}
else
{
Log.v("Main", "old instance");
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
Log.v("Main", "save instance");
savedInstanceState.putString("test", "my test string");
super.onSaveInstanceState(savedInstanceState);
}
public void buttonClick(View view)
{
Intent intent = new Intent(this, Activity2.class);
startActivity(intent);
}
Here is my code for Activity B, when I press a button to go back to activity A:
public void onBack(View view)
{
NavUtils.navigateUpFromSameTask(this);
}
To answer your question, have a look at the android doc: https://developer.android.com/reference/android/app/Activity.html#onRestoreInstanceState(android.os.Bundle)
It says that onRestoreInstanceState is called after onStart() method in the activity lifecycle.
Saving and restoring state is meant to save the current temporary data that is obsolete when user exits the application.
When you minimize or leave the Activity by opening next one it might be killed by the system due to lack of resources and restarted with savedInstanceState when you get back to it. So use onSaveInstanceState() only for saving minimize-restore session data or data that should be preserved on rotation.
So if you start a new Activity in front and get back to the previous one (what you are trying to do), the Activity A might not be killed (just stopped) and restarted without going being destroyed. You can force killing it and restoring by checking Don't keep activities in developer options menu.
If you call finish() or remove the Activity from recent task list the savedInstanceState will not be passed to onCreate() since the task was cleared.
If the value must be persistent consider using SharedPreferences.
This happens because you are navigating the hard way. If you used the phone's default back button navigation, your onCreate would get the bundle passed in.
To circumvent this issue, I suggest you save your state to shared preferences as well as a back up. When the bundle is null, restore it from the shared preferences.
reference
onSaveInstanceState
... onPause()-> onSaveInstanceState() -> onStop() -> onDestory()
onRestoreInstanceState
onCreate()-> onStart()-> onRestoreInstanceState()-> onPostCreate(Bundle) ...
Or You can use LiveData. Save the states in it and observe.If the device rotates it'll update the views accordingly.
After onStart() which is after onCreate()
I used in this case a flag and SharedPreferences. This should work, and when you change the screen orientation.

Categories

Resources