Як я можу правильно повернутися до батьківської діяльності?


179

У моєму додатку для Android є 2 дії (A і B), і я використовую намір перейти від активності 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>

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

Тож після того, як я зателефонував у BI, я можу скористатися кнопкою UP, щоб повернутися до активності A. Проблема полягає в тому, що програма, схоже, знову викликає функцію onCreate () -функції діяльності A, і це не та поведінка, яка мені потрібна. Мені потрібна активність A, щоб виглядати так само, як виглядала раніше, ніж я називав діяльність B.

Чи є спосіб досягти цього?

Спасибі заздалегідь

Редагувати:

Я не писав жодного коду, щоб почати діяльність B з діяльності A. Я думаю, що це автоматично генерується затемненням.

Клас 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);
}

Розмістіть свій код, щоб почати Дія А з B ..
user370305

Якщо я правильно вас зрозумів, ви можете використовувати startActivityForResult () і повернути результатCode або щось подібне.
Закон Гіменеза

Будь ласка, оновіть правильну відповідь, що позначена вами! ПРАВИЛЬНА відповідь надходить від LorenzCK - не від користувача ......! Позначення цього правильним вводить в оману і навіть більше програмістів неправильно розуміють навігацію на відміну від зворотної навігації!
Зордід

Боже, стільки невірних відповідей тут, чи можете ви допомогти в цьому?
Зордід

@ashiaka - правильна відповідь відповідно до дизайну коду оновлена.
user370305

Відповіді:


334

Ви оголосили активність A зі стандартом launchModeу маніфесті Android. Згідно з документацією , це означає:

Система завжди створює новий екземпляр діяльності в цільовому завданні і направляє намір до цього.

Тому система змушена відтворити активність A (тобто виклик onCreate), навіть якщо стек завдань обробляється правильно.

Щоб виправити цю проблему, вам потрібно змінити маніфест, додавши наступний атрибут до декларації про активність:

android:launchMode="singleTop"

Примітка: виклик finish()(як пропонувалося як рішення раніше) працює лише тоді, коли ви повністю впевнені, що екземпляр B діяльності, який ви припиняєте, працює над інстанцією діяльності A. У складніших робочих процесах (наприклад, запуск діяльності B з повідомлення) це може бути не так, і ви повинні правильно запустити діяльність A з B.


11
Ось пояснення від докерів Android: "Стандартний" та "єдиний" режими відрізняються один від одного лише в одному відношенні: Кожен раз, коли з'являється новий намір для "стандартної" діяльності, створюється новий екземпляр класу для відповіді на цей намір Кожен екземпляр обробляє один намір. Так само може бути створений новий екземпляр активності "singleTop" для обробки нового наміру. Однак якщо цільове завдання вже має наявний екземпляр активності у верхній частині стека, цей екземпляр отримає новий намір (у виклику onNewIntent ()); новий примірник не створюється.
kpsfoo

Зауважте, що згідно з документацією navigateUpFromSameTask(...) слід додавати FLAG_ACTIVITY_CLEAR_TOPдо upIntent(через navigateUpTo(...)що має спричинити таку саму поведінку (згідно з цим посібником ), але прапор ніколи не встановлюється - і тому ця відповідь має сенс
Anigif

82

Оновлений відповідь: Дизайн навігації вгору

Ви повинні заявити, яка діяльність є відповідним батьківським для кожної діяльності. Це дозволяє системі полегшувати схеми навігації, такі як Up, оскільки система може визначати логічну батьківську активність з файлу маніфесту.

Тож для цього вам слід оголосити свою батьківську активність у тезі "Активність" з атрибутом

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);
}

Стара відповідь: (Без навігації вгору, за замовчуванням Назад Навігація)

Це трапляється лише в тому випадку, якщо ви знову починаєте Діяльність А з Діяльності В.

Використання startActivity().

Замість цього з Activity A запустіть Activity B, використовуючи startActivityForResult()та переміняючи onActivtyResult()в Activity A.

Тепер у діяльності B просто натисніть finish()кнопку Вгору. Отже, тепер ви перейшли до діяльності A, onActivityResult()не створюючи знову активність A.


Я не знаю, куди називається startActivity () у діяльності B. Я опублікував вихідний код діяльності B ...
ashiaka

18
Замість рядка коду NavUtils.navigateUpFromSameTask(this); напишіть finish().
user370305

4
Постає питання, а чому Google нічого не згадує про finish()або startActivityForResult()у своїй документації щодо навігації ( developer.android.com/design/patterns/navigation.html )?
wired00

це звучить як трудомістке вирішення. @LorenzCK відповідь здається набагато кращою.
carmen_munich

Дякуємо за використання NavUtils.navigateUpFromSameTask (це). Великий плюс! Я шукав такий метод, як замінити закінчення (), який не повертається до батьківської діяльності за певних обставин. закінчення () по суті повертається до попередньої діяльності, яка не обов'язково є батьківською діяльністю.
Hong

22

Я мав майже таку ж установку, що призводило до тієї ж небажаної поведінки. Для мене це спрацювало: додавання такого атрибуту до діяльності A у Manifest.xmlмоєму додатку:

android:launchMode="singleTask"

Докладніші пояснення див. У цій статті .


1
З моєї точки зору правильне рішення проблеми. Це буде вести себе так само, як якщо ви викликали закінчення (), якщо активність існує в стеку завдань. Якщо це не так, він буде створений і запущений.
Йоган

5
Це не правильний спосіб, оскільки це створюватиме нове завдання без потреби кожного разу, замість цього слід використовувати запускMode = "singleTop".
kpsfoo

19

Хоча старе питання, ось ще (имхо найчистіше і найкраще) рішення , як і всі попередні відповіли не працював для мене , так як я deeplinked активності B від Widget .

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


7

Кращий спосіб досягти цього - за допомогою двох речей: call:

NavUtils.navigateUpFromSameTask(this);

Тепер для того, щоб це працювало, потрібно мати свій файл маніфесту, що активність A має батьківську активність B. Батьківській діяльності нічого не потрібно. У версії 4 і вище ви отримаєте гарну стрілку назад без додаткових зусиль (це можна зробити і на нижчих версіях, а також з невеликим кодом, я викладу це нижче) Ви можете встановити ці дані на маніфесті-> вкладка програми у графічному інтерфейсі (прокрутіть униз до назви батьківської діяльності та покладіть її вручну)

Вузол підтримки:

якщо ви хочете підтримувати версію нижче версії 4, вам також потрібно включити метадані. клацніть правою кнопкою миші на активність, додавання> метадані, ім'я = android.support.PARENT_ACTIVITY та value = your.full.activity.name

щоб отримати гарну стрілку в нижчих версіях:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Зверніть увагу, вам знадобиться бібліотека підтримки версії 7, щоб все це працювало, але воно того варте!


5

Те, що для мене працювало, додало:

    @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()методі


4

Я спробував android:launchMode="singleTask", але це не допомогло. Працював для мене, використовуючиandroid:launchMode="singleInstance"


Додавання android: launchMode = "singleInstance" до батьківської активності вирішило для мене проблему
emir

4

Додавши до @ 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);
}

Це запустить нове завдання та запустить батьківську активність вашої діяльності, яку ви можете визначити в Manifest, як наведено нижче версії Min SDK <= 15

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

Або за допомогою, parentActivityNameякщо його> 15


Примітка: заявляйте про parentActivityNameSDK> 15, інакше це
призведе до

3

У мене була схожа проблема з використанням 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>

Я видалив com.example.myfirstapp з імені батьківської діяльності, і він працював належним чином


2

Додайте до своєї діяльності маніфест із атрибутом

android:launchMode="singleTask"

добре працює для мене


1
Потік Comlete є таким, як загальнодоступний загальнодоступний буфер @Override onOptionsItemSelected (елемент MenuItem) {switch (item.getItemId ()) {case android.R.id.home: NavUtils.navigateUpFromSameTask (це); повернути правду; } повернути super.onOptionsItemSelected (елемент); }
Правеш Кумар

Додайте до свого маніфесту <активність android: name = ". MainActivity" android: label = "@ string / title_activity_main"> </activity> <активність android: name = ". CreateEventActivity" android: label = "@ string / title_activity_create_event" android : startMode = "singleTask" android: parentActivityName = ". MainActivity"> <метадані android: name = "android.support.PARENT_ACTIVITY" android: value = ". MainActivity" /> </activity>
Правеш Кумар

2

У класі 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>

Це допоможе тобі


1
    @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);

як натисніть Назад


1

спробуйте це:

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);
}

0

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

Це спеціально вирішило мою проблему, оскільки я не хотів, щоб Android створював новий екземпляр попередньої активності після натискання Upкнопки на панелі інструментів - натомість я хотів використовувати наявний екземпляр попередньої активності, коли я піднімався в ієрархію навігації.

Довідка: android: launchMode


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.