4

I want to know the default implementation of onBackPressed() in Activity. How to deal with the Activity recover in the default implementation of onBackPressed()?.

The following is the issues I suffer from. I have a test Activity code like this:

public class MainActivity extends Activity {
    public static boolean test = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this,"is "+test,Toast.LENGTH_LONG).show();
        test = !test;
    }
}

When I first enter the app, I get 'is false'. Then I click back button and get to the home screen. After that, when I enter the app, I get the Toast 'is true'. I think the onBackPressed() should kill my app when it gets back to the home screen, but It does not. This is my question.

If I override onBackPressed() like this

@Override
public void onBackPressed() {
//  super.onBackPressed();
    finish();
    try {
        android.os.Process.killProcess(android.os.Process.myPid());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

I always get the Toast 'is false' after I enter the app.

Can anyone explain this problem and tell me what the default implementation of onBackPressed()?

I'd like to know the flow process in onBackPressed() in detail. I have read some of the source code on onBackPressed(), but I couldn't understand it well.

Thanks in advance.

Onik
  • 19,396
  • 14
  • 68
  • 91
xxxzhi
  • 471
  • 3
  • 12
  • 1
    It seems that everything works as it should work. You destroy your process and `false` field "clears". So what's the problem? – eleven Jan 22 '16 at 15:18
  • no. I just click backpress menu button.after I return to home screen, and after that, I enter this app again, but the test is become true. That means, the default onBackPressed did not destroy my process. – xxxzhi Jan 22 '16 at 15:29
  • Default `onBackPressed` does not destroy your process. It destroys your `activity` and all activity related objects(fragments, ui). – eleven Jan 22 '16 at 15:49
  • @Foxinsocks destroy my activity and not recycle the MainActivity.class ? – xxxzhi Jan 22 '16 at 16:07
  • What do you mean `not recycle`? `ClassLoader` of your activity doesn't unload `class`, if you mean this. – eleven Jan 22 '16 at 16:11
  • If you quit all activities of the application, the process is not immediately destroyed by default. – EpicPandaForce Jan 22 '16 at 16:30

2 Answers2

1

From the AOSP Activity class found here:

/**
 * Called when the activity has detected the user's press of the back
 * key.  The default implementation simply finishes the current activity,
 * but you can override this to do whatever you want.
 */
public void onBackPressed() {
    if (mActionBar != null && mActionBar.collapseActionView()) {
        return;
    }

    if (!mFragments.getFragmentManager().popBackStackImmediate()) {
        finishAfterTransition();
    }
}

So basically when you call finish, the process is not actually destroyed. You can read more about that here. This means that the memory in your app isn't destroyed, so when you restart your app, the boolean value from before is remembered.

In the case of your overridden implementation, you are explicitly destroying the process, which will clear memory of your activity state, so when you restart the app, the boolean initialization will occur again.

Community
  • 1
  • 1
vdelricco
  • 749
  • 4
  • 15
  • can you describle all the process in detail about onBackPressed? thanks. In fact, I have read popBackStackImmediate() source . I just can't describle all the thing what the android does in onBackPressed. – xxxzhi Jan 22 '16 at 15:37
  • 1
    Consider this simple example: You are using your android phone and are at the home screen. There is only 1 fragment open at that time (the home screen). This means there are no fragments on the fragment stack. Now, consider opening a browser. The browser opens, and there is a new fragment open now. The home screen fragment gets placed on the stack now, so there is 1 item on the stack. Now consider using the back button again. Android will check if there is a fragment in the stack. Since there is 1, it will close the current fragment and resume the fragment on the stack. I hope this is helpful. – vdelricco Jan 22 '16 at 16:05
1

The default implementation of Activity's onBackPressed() probably won't tell you a lot about the actual Activity/application lifetime. You should dig much dipper to understand the internal Android (and Linux) "mechanics" on application/process killing.

What an application developer should know is that once an Activity is in background (Home button pressed, incoming call received etc., i.e. onPause() followed by onStop() have been invoked) its process may (similar to what you did with android.os.Process.killProcess(...)) or may NOT be killed. See Multitasking the Android Way by Dianne Hackborn for the reference.

As to finishing an Activity by pressing the back button, it does not mean its instance will be immediately killed and the memory garbage collected (see this answer). It just means a new instance of the Activity will be created next time you navigate back to it.

Regarding your code and the statement that

When I first enter the app, I get 'is false'. Then I click back button and get to the home screen. After that, when I enter the app, I get the Toast 'is true'. I think the onBackPressed() should kill my app when it gets back to the home screen, but It does not.

This is the case when the system didn't kill the process while the Activity were in background (again, it is not guaranteed). If it did, the Toast would have shown false.

In order to check that a new instance of MainActivity is created each time you press the back button and then navigate back to the app, I don't recommend to use a static variable, - it appears to be not that obvious (see, for instance, is it possible for Android VM to garbage collect static variables... or Are static fields open for garbage collection?).

Besides you're simply switching between true and false that might be confusing. Instead of using a static variable you might use a non-static one incrementing it, for example, or toast the hash code of the current Activity instance, like Toast.makeText(this,"is " + this.hashCode(), Toast.LENGTH_LONG).show(). By doing this the Activity lifecycle should act as per the documentation.

If I override onBackPressed() ... I always get the Toast 'is false' after I enter the app.

This is more or less similar to what if the system kills your app's process.

Community
  • 1
  • 1
Onik
  • 19,396
  • 14
  • 68
  • 91
  • Thx. BTW, does `onBackPressed` invoke `onDestory`? – xxxzhi Jan 23 '16 at 03:08
  • Not directly. Call to `onBackPressed()` implicitly results in invoking `onDestroy()` by the system. – Onik Jan 23 '16 at 12:50
  • what's mean implicitly? I have tried `onBackPressed`. The app return home screen directly, and not log onDestroy. – xxxzhi Jan 23 '16 at 14:01
  • The system may not call `onDestroy()` when it's on low memory, but normally it does invoke it. I guess you forgot to remove `Process.killProcess()` which terminates the process brutally without waiting for any callbacks... "implicitly" means "all the magic" happens not in the method, it starts there. An `Activity` is just an application component, basically a `Java` object. If you want to know what is going on under the hood, beneath `Java` app components, I recommend to observe the sources and read [this book](http://www.amazon.com/Embedded-Android-Porting-Extending-Customizing/dp/1491920718) – Onik Jan 23 '16 at 14:46
  • oh, yeah, I forgot to remove `Process.killProcess()` – xxxzhi Jan 24 '16 at 04:20