onPause() and onStop() in Activity
Asked Answered
F

6

22

I am new to Android development and I am still not able to understand the onPause() and onStop() methods in an activity.

In my app, I have a static class that I name Counter, and it keeps the state of variables in memory for the app. My app runs fine in the emulator. What I was trying to test was differential behavior of onPause() versus onStop().

For onPause, I wanted the values stored in the Counter class's members retained, whereas calling onStop() I wanted the counter values reset to zero. So I override onStop() and set the variables inside the counter class to zero. However, in the emulator, I cannot seem to get the app in the Paused state. In the emulator, I open my app, exercise it. Then I hit the home button (not the back button) of the emulator, and launch another app, believing that this would mimic onPause() activity. However, the emulator does not appear to honor this (I am using an armeabi v7a emulator), it seems to always be calling onStop() because my counter values all go back to zero, per my override in onStop(). Is this inherent to the emulator or am I doing something wrong to get my activity into the paused state?

Foregut answered 8/7, 2012 at 22:33 Comment(2)
Can you include code to emphasize your problem?Nigelniger
Refer to [Under what circumstances would a Dialog appearing cause onPause() to be called?][1] [1]: #7241416Aestheticism
A
27

I'm not sure which emulator you are testing with, but onPause is the one method that is always guaranteed to be called when your Activity loses focus (and I say always because on some devices, specifically those running Android 3.2+, onStop is not always guaranteed to be called before the Activity is destroyed).

A nice way to understand the Activity lifecycle for beginners is to litter your overriden methods with Logs. For example:

public class SampleActivity extends Activity {

    /**
     * A string constant to use in calls to the "log" methods. Its
     * value is often given by the name of the class, as this will 
     * allow you to easily determine where log methods are coming
     * from when you analyze your logcat output.
     */
    private static final String TAG = "SampleActivity";

    /**
     * Toggle this boolean constant's value to turn on/off logging
     * within the class. 
     */
    private static final boolean VERBOSE = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (VERBOSE) Log.v(TAG, "+++ ON CREATE +++");
    }

    @Override
    public void onStart() {
        super.onStart();
        if (VERBOSE) Log.v(TAG, "++ ON START ++");
    }

   @Override
    public void onResume() {
        super.onResume();
        if (VERBOSE) Log.v(TAG, "+ ON RESUME +");
    }

    @Override
    public void onPause() {
        super.onPause();
        if (VERBOSE) Log.v(TAG, "- ON PAUSE -");
    }

    @Override
    public void onStop() {
        super.onStop();
        if (VERBOSE) Log.v(TAG, "-- ON STOP --");
    }

   @Override
    public void onDestroy() {
        super.onDestroy();
        if (VERBOSE) Log.v(TAG, "- ON DESTROY -");
    }
}
Antemundane answered 8/7, 2012 at 22:57 Comment(6)
Thanks Alex, I already have the log markups, I should have mentioned that. What the logs are showing me is that onPause() does indeed get called. The trouble for me in the emulator is that I want onStop() not to be called. So when I hit the home button, my logs show me that onPause() indeed is called, as expected. However, when I switch apps in the emulator (from my app to the web browser for example), my logs also show me that onStop() for my app is getting called. I would expect onStop() only to get called if the sys is starved for resources, and perhaps the VM is?Foregut
Hmm... did you mess around with the Developer settings? Settings --> Developer settings --> destroy all activities, perhaps is checked? Other than that, it's important to understand that onStop is never guaranteed to be called... as seen here: bit.ly/OMB0asAntemundane
@StephanDoliov I mentioned checking the developers settings because it seems odd that onStop is NEVER called. I'm not sure why that is happening. I'm betting that if you test on an actual device you won't get the same behavior though. What happens when you press the "home" button? This is one of the popular ways onStop is called.Antemundane
It is important to note that onStop() is now guaranteed to be called for post-Honeycomb devices. See: https://mcmap.net/q/138613/-is-activity-onstop-guaranteed-to-be-called-api-11/3960852Sandglass
It is now 2018. But, the documentation shows onStop() is killable for all version , and shows onPause() is killable in pre-honeycomb - i.imgur.com/CYpQdSL.png (developer.android.com/reference/android/app/Activity.html)Eskimoaleut
Thanks, I was treating a bug for days, without idea whats going on, this logs save me!Britska
R
13

I know your question was 6 months ago but in case someone else stumbles on this question:

am I doing something wrong to get my activity into the paused state.

Yes, you are. This:

I hit the home button (not the back button) of the emulator, and launch another app, believing that this would mimic onPause() activity.

Hitting the home button will indeed call the onPause() method but because the home button makes your activity no longer visible it will then call the onStop() method (like patriot & milter mentioned).

As per the Activities developer reference (http://developer.android.com/guide/components/activities.html) you can display a dialog or simply put the device to sleep.

Alternatively, you call an activity that will only partially obstruct the calling activity. So call an activity that creates a window with a view of size:

 android:layout_width="100dp"
 android:layout_height="100dp"

Which doesn't cover the entire screen, thus leaving the calling activity behind partially visible, thus calling only calling activity's onPause() method.

Clone that activity so that both view sizes are "match_parent" instead of "100dp" and call it and both the onPause() and onStop() methods of the calling activity will be called because the calling activity won't be visible.

There can be exceptions of course, like if the called activity causes an app crash in either of its onCreate(), onStart() or onResume() then the onStop() of the calling activity will not be called, obviously, I'm just talking about the general case here.

Roadside answered 3/4, 2013 at 13:49 Comment(0)
R
4

The differences between when onPause() and onStop() are called can be pretty subtle. However, as explained here, onPause() will usually get executed when another activity takes focus (maybe as a pop up, or transparent window) while the current activity is still running. If you navigate away from the app completely (for example, by hitting the home button), the activity is no longer visible and the system may execute onStop(). I only say may because, as Alex mentioned, there are some cases where onStop doesn't get called before the Activity is destroyed.

Rachelrachele answered 8/7, 2012 at 22:46 Comment(1)
how do I ensure that onStop() will be called after I click back button or call finish ?Penholder
T
2

onPause():

"If an activity has lost focus but is still visible (that is, a new non-full-sized or transparent activity has focus on top of your activity), it is paused. A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager), but can be killed by the system in extreme low memory situations."

onStop():

"If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere."

Taken from android reference activity class: http://developer.android.com/reference/android/app/Activity.html

Trachyte answered 8/7, 2012 at 22:59 Comment(0)
B
1

If you are emulating Android 4.x you can control how the system handles background activities using Settings -> Developer Options -> Don't keep activities and Background process limit. For older versions there is an app called Dev Tools which contains the same settings. However, on low memory conditions the system can disregard those settings and terminate your application. Increasing the amount of memory assigned to the emulator might help.

Also, if you are re-launching your app from Eclipse, it will kill the previous process instead of gracefully terminating it.

Baboon answered 8/7, 2012 at 23:6 Comment(0)
A
1

I agree with milter!

onPause():

"If an activity has lost focus but is still visible (that is, a new non-full-sized or transparent activity has focus on top of your activity), it is paused. A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager), but can be killed by the system in extreme low memory situations."

If you swap applications without pressing Back (press and hold HOME) then the OS is going to call onPause. When you return to your activity (press and hold HOME again) in onResume you should have all of your private variables preserved. But you can't control the user, right?!

if you anticipate that the user is going to leave your app and the OS calls your onStop you better save your data if you intend to resume where you left-off.

I have a Timer also, I need to save the elapsed time so when the user returns I can restore the data. here is my example to save:

@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.putLong("elapsedTime", elapsedTime);
  // etc. 
} 

And my code to restore:

@Override 
public void onRestoreInstanceState(Bundle savedInstanceState) { 
  super.onRestoreInstanceState(savedInstanceState); 
  // Restore UI state from the savedInstanceState. 
  // This bundle has also been passed to onCreate. 

  elapsedTime = savedInstanceState.getLong("elapsedTime");
} 

Place these methods inside of your class and you are good to go. Keep in mind that the string "elapsedTime" in my case is a KEY to the system and it must be unique. Use unique strings for each piece of data that you would like to save. For example "startClock", "ClockTextColor", etc...

Avalos answered 9/6, 2013 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.