Как я могу вернуться к родительской деятельности правильно?


у меня есть 2 действия (A и B) в моем приложении для android, и я использую намерение перейти от действия A к действию B. использование parent_activity включено:

 <activity
        android:name=".B"
        android:label="B" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.app_name.A" />
  </activity>

Я также использую тему, которая обеспечивает кнопку вверх.

поэтому после того, как я вызвал activity B, я могу использовать кнопку UP, чтобы вернуться к activity A. проблема в том, что приложение, похоже, вызывает onCreate ()-функция активности a снова, и это не то поведение, которое мне нужно. Мне нужно действие A, чтобы выглядеть так же, как это выглядело до того, как я назвал действие B.

есть ли способ достичь этого?

спасибо заранее

EDIT:

Я не писал никакого кода для запуска activity B из activity A. Я думаю, что он автоматически генерируется eclipse.

класс B выглядит так:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}


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

16 ответов:

вы объявили активность A со стандартом launchMode в манифесте Android. Согласно документация, что означает следующее:

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

поэтому система вынуждена воссоздать действие A (т. е. вызов onCreate) даже если стек задач обрабатывается правильно.

чтобы решить эту проблему, вам нужно измените манифест, добавив в объявление действия a следующий атрибут:

android:launchMode="singleTop"

Примечание: вызов finish() (как было предложено в качестве решения раньше) работает только когда вы абсолютно точно что экземпляр activity B, который вы завершаете, живет поверх экземпляра activity A. в более сложных рабочих процессах (например, запуск activity B из уведомления) это может быть не так, и вам нужно правильно запустить упражнение а от В.

Обновленный Ответ: Вверх По Дизайну Навигации

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

поэтому для этого вам нужно объявить свою родительскую активность в теге Activity с атрибутом

android:parentActivityName

например,

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

С родительской активностью, объявленной таким образом, вы можете перейти к соответствующему родителю, как показано ниже,

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    // Respond to the action bar's Up/Home button
    case android.R.id.home:
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

поэтому, когда вы называете NavUtils.navigateUpFromSameTask(this); этот метод завершает текущую операцию и запускает (или возобновляет) соответствующую родительскую операцию. Если целевое родительское действие находится в заднем стеке задачи, оно переносится вперед, как определено FLAG_ACTIVITY_CLEAR_TOP.

и для отображения кнопки вы должны объявить setDisplayHomeAsUpEnabled():

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

старый ответ: (без навигации вверх, навигация по умолчанию назад)

это произойдет только в том случае, если вы снова начинаете действие A С действия B.

используя startActivity().

вместо этого из действия a начните действие B с помощью startActivityForResult() и переопределить onActivtyResult() в работе А.

теперь в действии B просто позвоните finish() на кнопку Вверх. Итак, теперь вы направлены на деятельность A onActivityResult() без создания снова деятельности..

у меня была почти такая же настройка, приводящая к тому же нежелательному поведению. Для меня это работало: добавление следующего атрибута к действию A в Manifest.xml Мои приложения:

android:launchMode="singleTask"

посмотреть в этой статье для более подробного объяснения.

хотя старый вопрос, вот еще одно (имхо самое чистое и лучшее) решение, так как все предыдущие ответы не работали для меня, так как я deeplinked Activity B С виджет.

public void navigateUp() {
final Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot()) {
    Log.v(logTag, "Recreate back stack");
        TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities();
  } else {
    NavUtils.navigateUpTo(this, upIntent);
  }
}

[https://stackoverflow.com/a/31350642/570168 ]

но также см.: https://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android

лучший способ достичь этого-использовать две вещи: звоните:

NavUtils.navigateUpFromSameTask(this);

теперь, чтобы это работало, вам нужно иметь состояние файла манифеста, что действие A родитель Б. активность родительской активности ничего не нужно. В версии 4 и выше вы получите хорошую стрелку назад без дополнительных усилий (это можно сделать и на более низких версиях с небольшим кодом, я поставлю его ниже) Вы можете установить эти данные на вкладке манифест->приложение в графическом интерфейсе (прокрутите вниз до имя родительского действия, и положить его вручную)

поддержки узел:

Если вы хотите поддерживать версию ниже версии 4, Вам также необходимо включить метаданные. щелкните правой кнопкой мыши на активности, добавить - >метаданные, имя =android.поддержка.PARENT_ACTIVITY и value = your.full.activity.name

чтобы получить хорошую стрелку в более низких версиях, а также:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

обратите внимание, что вам понадобится поддержка библиотеки версии 7, чтобы все это работало, но это того стоит это!

пробовал android:launchMode="singleTask", но это не помогло. Работал для меня с помощью android:launchMode="singleInstance"

добавление к ответу @LorenCK, изменить

NavUtils.navigateUpFromSameTask(this);

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

Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    TaskStackBuilder.create(this)
            .addNextIntentWithParentStack(upIntent)
            .startActivities();
} else {
    NavUtils.navigateUpTo(this, upIntent);
}

это запустит новую задачу и запустит родительскую активность вашей активности, которую вы можете определить в манифесте, как показано ниже версии min SDK

<meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.app_name.A" />

или через parentActivityName если > 15

то, что сработало для меня, добавляло:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onBackPressed() {
        finish();
    }

до TheRelevantActivity.java и теперь он работает, как ожидалось

и да, не забудьте добавить:

getSupportActionbar.setDisplayHomeAsUpEnabled(true); на onCreate() метод

У меня была аналогичная проблема с использованием android 5.0 с плохим именем родительской активности

<activity
        android:name=".DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName=".MainActivity" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>

Я удалил ком.образец.myfirstapp от имени родительского действия, и он работал правильно

добавьте в свой манифест активности информацию с атрибутом

android:launchMode="singleTask"

работает хорошо для меня

в классе Java: -

    toolbar = (Toolbar) findViewById(R.id.apptool_bar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setTitle("Snapdeal");

    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

В Манифесте :-

<activity
            android:name=".SubActivity"
            android:label="@string/title_activity_sub"
            android:theme="@style/AppTheme" >
            <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"></meta-data>
    </activity>

Это поможет вам

попробуйте это:

Intent intent;
@Override
public void onCreate(Bundle savedInstanceState) {
intent = getIntent();   
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_b, menu);
return true;
}  


@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
    case android.R.id.home:
    NavUtils.navigateUpTo(this,intent);
        return true;
}
return super.onOptionsItemSelected(item);
}
    @Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
    case android.R.id.home:
        finish();
        return true;
}
return super.onOptionsItemSelected(item);

Как назад нажмите

вход в мой манифест и добавление android:launchMode="singleTop" активность сделал трюк для меня.

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

ссылки: android: launchMode

попробуйте это решение использовать NavUtils.navigateUpFromSameTask (this); в дочернем действии: https://stackoverflow.com/a/49980835/7308789

использовать finish() в активности для возврата, когда в вашем событии щелчка.