问题
Right off the top, I want to clarify something: The button that I am struggling with is NOT the back
button. I am referring to the up/home
button in the ActionBar / Toolbar at the top of the app, not the Android button at the bottom. There are a few posts of a similar nature, but they address the back button, not the up button.
Here is the situation: I have an Activity A that has a ListView fragment. When the user clicks on a list view item, it launches Activity B. Pretty typical. Activity A has an EditText
field in the toolbar that allows the user to enter a search parameter. If the user hits the up/home
button from Activity B, I return successfully to Activity A. However, I want Activity A to show the same text in the EditText
field that was there when they left it. If the user hits the back
button, this text is restored. But if they navigate with the up/home
button, the EditText
field is empty.
Using some log statements, I can see that when a list item is tapped from activity A, onSaveInstanceState
and onStop
are both called (but onDestroy
is NOT called at that point.) From activity B, when the up/home
button is tapped, onDestroy
from activity A is immediately called, followed by onCreate
, etc. However, the bundle savedInstanceState
is null, presumably since onDestroy
was just called.
Why is onDestroy
called when returning to Activity A? This makes no sense to me. Here is what I have in the manifest:
<activity
android:name=".Activity.ActivityA"
android:label="@string/app_name"
android:parentActivityName=".Activity.ParentActivity"
android:theme="@style/AppTheme"
android:launchMode="singleTop"
android:windowSoftInputMode="stateVisible" />
<activity
android:name=".Activity.ActivityB"
android:label="@string/app_name"
android:parentActivityName=".Activity.ActivityA"
android:theme="@style/AppTheme" />
Here are the relevant methods in Activity A:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
actionBar = getSupportActionBar();
if (actionBar != null)
initializeActionBar();
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Log.d(TAG, "on create");
if (savedInstanceState != null) {
Log.d(TAG, "saved instance state not null");
if (savedInstanceState.getString("search_text") != null)
etSearch.setText(savedInstanceState.getString("search_text"));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("search_text", etSearch.getText().toString());
Log.d(TAG, "on Save instance state");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, "on restore instance state");
if (savedInstanceState != null) {
if (savedInstanceState.getString("search_text") != null)
etSearch.setText(savedInstanceState.getString("search_text"));
}
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "on resume");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "on stop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "on destroy");
}
private void initializeActionBar() {
actionBar.setCustomView(R.layout.actionbar_with_edittext);
etSearch = (EditText) actionBar.getCustomView().findViewById(R.id.actionbar_searchfield);
etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN) {
initiateNewSearch();
etSearch.clearFocus();
}
return false;
}
});
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(etSearch, InputMethodManager.SHOW_IMPLICIT);
etSearch.requestFocus();
}
I don't think that any of the code in Activity B is relevant here.
This is my console output when a user taps on a listview item in Activity A:
on Save instance state
on stop
And then this is what is generated when the user taps on the up/home
button from activity B:
on destroy
on create
on resume
If there is anything else that may be of help, please let me know. Thanks for any advice!
回答1:
I don't know why default up button implementation creates a new activity but a working solution for me is to override onOptionsItemSelected
:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id== android.R.id.home ){
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
Also this solution works for me:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = NavUtils.getParentActivityIntent(this);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
NavUtils.navigateUpTo(this, intent);
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
回答2:
I had this problem too, and after a little more digging found the correct solution is to make a change in the manifest to add the following to your parent activity:
android:launchMode="singleTop"
Details are explained here.
来源:https://stackoverflow.com/questions/37222278/up-button-calls-ondestroy-of-parent-activity