Завершить действие из другого занятия


101

Я хочу завершить одно действие другим, например:

В Activity [A] при нажатии кнопки я вызываю Activity [B], не завершая Activity [A].

Теперь в Activity [B] есть две кнопки: New и Modify . Когда пользователь нажимает кнопку «Изменить», выдает активность [A] из стека со всеми отмеченными опциями.

Но когда пользователь нажимает на Новой кнопке от активности [B], то я должен закончить операцию [A] из стека и перезагрузок , что активность [A] снова в стек.

Я пытаюсь, но не могу завершить действие [A] из стека ... Как мне это сделать?

Я использую код как:

Из действия [A]:

Intent GotoB = new Intent(A.this,B.class);
startActivityForResult(GotoB,1);

Другой метод в той же деятельности

public void onActivityResult(int requestCode, int resultCode, Intent intent) {

    if (requestCode == 1)
    {
        if (resultCode == 1) {
            Intent i = getIntent();
            overridePendingTransition(0, 0);
            i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
            finish();

            overridePendingTransition(0, 0);
            startActivity(i);
        }
    }
}

А в Activity [B] при нажатии кнопки:

setResult(1);
finish();

эй, вы хотели закончить одно действие с другого прямо ... тогда я отправил правильный ответ. Но почему вы проголосовали против?
Манджунатх

Здесь есть ветка с несколькими хорошими ответами: stackoverflow.com/questions/14355731/…
ab

Ответы:


188
  1. Сделайте свою деятельность A в файле манифеста: launchMode = "singleInstance"

  2. Когда пользователь нажимает кнопку «Новое», выполните FirstActivity.fa.finish();и вызовите новое намерение.

  3. Когда пользователь нажимает кнопку «Изменить», вызовите новое намерение или просто завершите действие B.

ПЕРВЫЙ ПУТЬ

В своем первом действии объявите одно Activity objectподобное:

public static Activity fa;
onCreate()
{
    fa = this;
}

теперь используйте этот объект в другом, Activityчтобы завершить подобное первое действие,

onCreate()
{
    FirstActivity.fa.finish();
}

ВТОРОЙ ПУТЬ

При вызове действия, FirstActivityкоторое вы хотите завершить, как только вы продолжите, вы можете добавить флаг во время вызоваFirstActivity

intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

Но с этим флагом действие будет завершено, даже если вы этого не хотите. и когда-нибудь, onBackесли вы хотите показать, FirstActivityвам придется вызывать его с помощью намерения.


6
Отличный ответ .. !!
Вайбхав Ваджани

94
Вы держите статическую ссылку на действие. Это никогда не исчезнет, ​​если вы не очистите его вручную откуда-то -> вы создаете утечку памяти!
DArkO

5
Хорошо, у вас есть +1 за нестандартное мышление: D, я бы просто перешел на singleTop. однако это все равно не будет моим первым выбором, когда я буду делать что-то подобное. Под кодом очистки я имел в виду способ избавиться от статической ссылки, чтобы не было утечки памяти, но это зависит от структуры приложения.
DArkO

6
Пожалуйста, не используйте первое решение, это совершенно неверно. При создании зомби-объекта вы обходите платформу Android действительно хакерским способом. Используйте BroadcastReceiver.
S-K '18

1
Отличные решения. Очень хорошо сработал для моей проблемы, в которой я переходил с действий A-> B-> C и на onBackPressed of C, я запускал новый экземпляр B. Но затем, если я сделал onBackPressed на этом новом экземпляре B, он раньше перейти к старому экземпляру B вместо старого экземпляра A (что я хотел). Итак, я последовал вашему первому методу в onBackPressed of C, и он дал мне то поведение, которое я хотел :) Большое спасибо :)
SoulRayder

88

Вы можете это сделать, но я думаю, вам не следует нарушать нормальный поток активности. Если вы хотите завершить свое действие, вы можете просто отправить трансляцию из вашего действия B в действие A.

Создайте широковещательный приемник перед началом занятия B:

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context arg0, Intent intent) {
        String action = intent.getAction();
        if (action.equals("finish_activity")) {
            finish();
            // DO WHATEVER YOU WANT.
        }
    }
};
registerReceiver(broadcastReceiver, new IntentFilter("finish_activity"));

Отправьте трансляцию из действия B в действие A, когда вы хотите завершить действие A из B

Intent intent = new Intent("finish_activity");
sendBroadcast(intent);

Надеюсь, у вас это сработает ...


Он показывает эту ошибку «Синтаксическая ошибка для токенов, вместо этого ожидается AnnotationName» на «registerReceiver (broadcast_reciever, new IntentFilter (" finish_activity "));". В чем дело?
Behzad

2
«вы не должны нарушать нормальный поток активности» +1 за это
S-K '18

11
Не забудьте broadcast_receiverunregisterReceiver()
отменить


Это решение. хороший
Паринда Раджапакша

17

Это довольно стандартный коммуникационный вопрос. Один из подходов - использовать ResultReceiver в действии A:

Intent GotoB=new Intent(A.this,B.class);
GotoB.putExtra("finisher", new ResultReceiver(null) {
    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        A.this.finish();
    }
});
startActivityForResult(GotoB,1);

а затем в Activity B вы можете просто закончить его по запросу следующим образом:

((ResultReceiver)getIntent().getExtra("finisher")).send(1, new Bundle());

Попробуйте что-нибудь подобное.


6
+1 просто, ((ResultReceiver) getIntent (). GetParcelableExtra ("finisher")). Send (1, new Bundle ());
Хамидреза Садег

12

Есть один подход, который вы можете использовать в своем случае.

Шаг 1: начните действие B с действия A

startActivity(new Intent(A.this, B.class));

Шаг 2: Если пользователь нажимает кнопку изменения, запускает действие A с помощью. FLAG_ACTIVITY_CLEAR_TOPКроме того, передайте флаг дополнительно.

Intent i = new Intent(B.this, A.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("flag", "modify");
startActivity(i);
finish();

Шаг 3: Если пользователь нажимает кнопку «Добавить», запускает действие A с помощью. FLAG_ACTIVITY_CLEAR_TOPТакже передайте флаг дополнительно. FLAG_ACTIVITY_CLEAR_TOPочистит все открытые действия до целевого и перезапустится, если в целевом действии не определен режим запуска

Intent i = new Intent(B.this, A.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("flag", "add");
startActivity(i);
finish();

Шаг 4: Теперь onCreate()метод Activity A, необходимо получить этот флаг.

String flag = getIntent().getStringExtra("flag");
if(flag.equals("add")) {
    //Write a code for add
}else {
    //Write a code for modifying
}


5

См. Мой ответ на вопрос о переполнении стека. Завершить все предыдущие действия .

Вам нужно добавить расширение Intent.FLAG_CLEAR_TOP. Этот флаг гарантирует, что все действия выше целевого действия в стеке завершены и что оно отображается.

Еще одна вещь, которая вам понадобится, - это SINGLE_TOPфлаг. С помощью этого вы не позволяете Android создавать новое действие, если оно уже создано в стеке.

Просто будьте осторожны, если действие уже было создано, намерение с этими флагами будет доставлено в вызываемом методе onNewIntent(intent)(вам необходимо перегрузить его для его обработки) в целевом действии.

Затем у onNewIntentвас есть метод с именем restart или что-то, что вызовет finish()и запустит новое намерение по отношению к самому себе, или есть repopulate()метод, который установит новые данные. Я предпочитаю второй подход, он менее затратный, и вы всегда можете выделить onCreateлогику в отдельный метод, который вы можете вызвать для заполнения.


4

Я только что применил решение Непстера и работает как шарм. Есть небольшая модификация для запуска из фрагмента.

К вашему фрагменту

// sending intent to onNewIntent() of MainActivity
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.putExtra("transparent_nav_changed", true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

И к вашему OnNewIntent () Activity, который вы хотите перезапустить.

// recreate activity when transparent_nav was just changed
if (getIntent().getBooleanExtra("transparent_nav_changed", false)) {
    finish(); // finish and create a new Instance
    Intent restarter = new Intent(MainActivity.this, MainActivity.class);
    startActivity(restarter);
}

2

Я думаю, что у меня самый простой подход ... нажимать new в B ..

Intent intent = new Intent(B.this, A.class);
intent.putExtra("NewClicked", true);
 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

и в A получить это

  if (getIntent().getBooleanExtra("NewClicked", false)) {
        finish();// finish yourself and make a create a new Instance of yours.
      Intent intent = new Intent(A.this,A.class);
      startActivity(intent);
    }

1

Я знаю, что это старый вопрос, некоторые из этих методов у меня не работали, поэтому для всех, кто смотрит в будущее или сталкивается с моими проблемами, это сработало для меня.

Я переопределил onPauseи вызвал finish()этот метод.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.