ActionBar up navigation воссоздает родительскую активность вместо onResume

Я использую рекомендуемый подход для Up Navigation, и мой код выглядит следующим образом:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            Intent h = new Intent(ShowDetailsActivity.this, MainActivity.class);
            h.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(h);
            return true;
        default: return super.onOptionsItemSelected(item);
    }
}

Здесь прецедент:

  • Я запускаю свое приложение, которое является "MainActivity"
  • Я нажимаю кнопку, чтобы перейти к "ShowDetailsActivity"
  • Я нажимаю на навигацию UP ActionBar

Проблема заключается в том, что после того, как я нажимаю UP, MainActivity снова и снова запускает методы onCreate() и теряет все состояние, а не начинает с типичного onResume(), как если бы я только что вызвал "finish()" из ShowDetailsActivity. Зачем? Как это всегда работает, и это ожидаемое поведение Android для воссоздания всех видов деятельности, которые ориентированы на использование навигационного подхода "Вверх"? Если я нажму кнопку "Назад", я получу ожидаемый жизненный цикл onResume.

Это мое решение, если Android "правильных" не существует:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            Intent upIntent = new Intent(this, MainActivity.class);
            if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
                NavUtils.navigateUpTo(this, upIntent);
                finish();
            } else {
                finish();
            }
            return true;
        default: return super.onOptionsItemSelected(item);
    }
}

Ответ 1

Добавьте в родительскую активность в файл манифеста следующее:

android:launchMode="singleTop"

относительно этого answer

Ответ 2

Причина, действия воссоздаются при использовании навигации вверх, для того чтобы андроид использовал стандартный режим запуска для этого, если вы не укажете другой режим. Это означает

"Система всегда создает новый экземпляр действия в целевая задача"

и, следовательно, активность воссоздана (см. документ здесь).

Решение должно было бы либо объявить режим запуска MainActivity как

android:launchMode="singleTop"

в AndroidManifest.xml
(всегда должен работать вместе с Intent.FLAG_ACTIVITY_CLEAR_TOP)

или вы можете добавить FLAG_ACTIVITY_SINGLE_TOP к своим флагам намерений, чтобы сообщить о деятельности, что ее нельзя воссоздавать, если она находится на задней панели, например

Intent h = NavUtils.getParentActivityIntent(this); 
h.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 
NavUtils.navigateUpTo(this, h);

Ответ 3

Этот код работал у меня:

Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    // This activity is NOT part of this app task, so create a new task
    // when navigating up, with a synthesized back stack.
    TaskStackBuilder.create(this)
        // Add all of this activity parents to the back stack
        .addNextIntentWithParentStack(upIntent)
        // Navigate up to the closest parent
        .startActivities();
} else {
    // This activity is part of this app task, so simply
    // navigate up to the logical parent activity.
    upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    NavUtils.navigateUpTo(this, upIntent);
}

return true;

Не требуется выполнить вызов finish().

Ответ 4

Что работает для меня (и я также считаю самым чистым), это изменить порядок действий на фронт. Если он не существует в стеке, он будет создан при наведении вверх.

Intent upIntent = NavUtils.getParentActivityIntent(this);
upIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(upIntent);
finish();
return true;

Ответ 5

вам просто нужно вернуться, чтобы не создавать активность снова.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            super.onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

Ответ 6

Начиная с Android 4.1 (API-уровень 16), вы можете объявить логического родителя каждого действия, указав в элементе атрибут android: parentActivityName. Если ваше приложение поддерживает Android 4.0 и ниже, включите библиотеку поддержки в приложение и добавьте элемент внутри. Затем укажите родительскую активность как значение для android.support.PARENT_ACTIVITY, соответствующее атрибуту android: parentActivityName.

<application ... >
...
<!-- The main/home activity (it has no parent activity) -->
<activity
    android:name="com.example.myfirstapp.MainActivity" ...>
    ...
</activity>
<!-- A child of the main activity -->
<activity
    android:name="com.example.myfirstapp.DisplayMessageActivity"
    android:label="@string/title_activity_display_message"
    android:parentActivityName="com.example.myfirstapp.MainActivity" >
    <!-- Parent activity meta-data to support 4.0 and lower -->
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.myfirstapp.MainActivity" />
</activity>

Если родительская активность имеет режим запуска или намерение вверх содержит FLAG_ACTIVITY_CLEAR_TOP, родительская активность переносится в начало стека и получает намерение посредством метода onNewIntent().

<activity
        android:launchMode="singleTop"
        android:name="com.example.myfirstapp.MainActivity">

    </activity>

В приведенном выше коде "SingleTop" может быть создан новый экземпляр действия "singleTop" для обработки нового намерения. Однако, если целевая задача уже имеет существующий экземпляр активности вверху своего стека, этот экземпляр получит новое намерение (в вызове onNewIntent()); новый экземпляр не создается.

Для подробной документации Нажмите здесь

Чтобы перейти, когда пользователь нажимает значок приложения, вы можете использовать статический метод класса NavUtils, navigateUpFromSameTask(). Для этого читайте документ, приведенный в ссылке выше.