Zakończ działanie z innego działania

101

Chcę zakończyć jedną czynność z innej, na przykład:

W działaniu [A] po kliknięciu przycisku wywołuję działanie [B] bez kończenia działania [A].

Teraz w ćwiczeniu [B] są dwa przyciski, Nowy i Modyfikuj . Gdy użytkownik kliknie modyfikację, zdejmij działanie [A] ze stosu z zaznaczonymi wszystkimi opcjami.

Ale kiedy użytkownik kliknie przycisk Nowy w Aktywności [B], będę musiał zakończyć Czynność [A] ze stosu i ponownie załadować to Aktywność [A] do stosu.

Próbuję, ale nie mogę zakończyć działania [A] ze stosu… Jak mogę to zrobić?

Używam kodu jako:

Z działania [A]:

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

Inna metoda w tym samym działaniu

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

W ćwiczeniu [B] po kliknięciu przycisku:

setResult(1);
finish();
Kanika
źródło
hej, chciałeś zakończyć jedną czynność od drugiej w prawo ... wtedy wysłałem odpowiedź, która jest poprawna. Ale dlaczego głosowałeś w dół?
Manjunath
Jest tu wątek z kilkoma fajnymi odpowiedziami: stackoverflow.com/questions/14355731/…
ab

Odpowiedzi:

189
  1. Umieść swoje działanie A w pliku manifestu: launchMode = "singleInstance"

  2. Kiedy użytkownik kliknie nowy, zrób FirstActivity.fa.finish();i wywołaj nowy zamiar.

  3. Kiedy użytkownik kliknie modyfikację, wywołaj nową intencję lub po prostu zakończ czynność B.

PIERWSZY SPOSÓB

W swojej pierwszej czynności zadeklaruj Activity objecttaką osobę:

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

teraz użyj tego obiektu w innym, Activityaby zakończyć pierwszą czynność w ten sposób,

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

DRUGI SPOSÓB

Podczas wywoływania aktywności, FirstActivityktórą chcesz zakończyć zaraz po przejściu, możesz dodać flagę podczas dzwonieniaFirstActivity

intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

Ale przy użyciu tej flagi działanie zostanie zakończone, nawet jeśli tego nie chcesz. i czasami, onBackjeśli chcesz to pokazać FirstActivity, będziesz musiał to nazwać używając intencji.

MKJParekh
źródło
6
Świetna odpowiedź..!!
Vaibhav Vajani
93
Trzymasz statyczne odniesienie do działania. To nigdy nie zniknie, dopóki nie usuniesz go ręcznie z jakiegoś miejsca -> tworzysz wyciek pamięci!
DArkO
5
Cóż, jest ok, masz moje +1 za nieszablonowe myślenie: D, po prostu zmieniłbym na singleTop. Jednak nadal nie będzie to mój pierwszy wybór, gdy robię coś podobnego. przez kod oczyszczania miałem na myśli sposób na pozbycie się statycznego odwołania, aby nie było wycieku pamięci, ale to zależy od struktury aplikacji.
DArkO
6
Proszę nikogo nie używać pierwszego rozwiązania, jest ono całkowicie błędne. Podczas tworzenia obiektu zombie omijasz strukturę Androida w naprawdę hakerski sposób. Użyj BroadcastReceiver.
S-K
1
Niesamowite rozwiązania. Zadziałało bardzo dobrze w przypadku mojego problemu, w którym przechodziłem od działań A-> B-> C i onBackPressed z C, uruchamiałem nową instancję B.Ale potem, jeśli zrobiłem onBackPressed na tej nowej instancji B, kiedyś przejdź do starej instancji B zamiast starej instancji A (co chciałem). Więc zastosowałem twoją pierwszą metodę w onBackPressed w C i dało mi to zachowanie, które chciałem :)
Wielkie
87

Możesz to zrobić, ale myślę, że nie powinieneś przerywać normalnej aktywności. Jeśli chcesz zakończyć swoją aktywność, możesz po prostu wysłać transmisję ze swojego działania B do działania A.

Utwórz odbiornik transmisji przed rozpoczęciem działalności 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"));

Wyślij transmisję z działania B do działania A, gdy chcesz zakończyć działanie A z działania B.

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

Mam nadzieję, że to zadziała ...

Bharat Sharma
źródło
Pokazuje ten błąd "Błąd składni na tokenach, zamiast tego oczekiwano AnnotationName" na "registerReceiver (broadcast_reciever, new IntentFilter (" finish_activity "));". Co jest nie tak?
Behzad
2
„nie powinieneś przerywać normalnej aktywności” +1 za to
S-K
11
Nie zapomnij wyrejestrować się broadcast_receiver zunregisterReceiver()
Jaec
To jest rozwiązanie. niezłe
Parinda Rajapaksha
17

To jest dość standardowe pytanie komunikacyjne. Jednym podejściem byłoby użycie elementu ResultReceiver w ćwiczeniu 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);

a następnie w Działaniu B możesz po prostu zakończyć to na żądanie w następujący sposób:

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

Spróbuj czegoś takiego.

Femi
źródło
6
+1 just, ((ResultReceiver) getIntent (). GetParcelableExtra ("finisher")). Send (1, new Bundle ());
Hamidreza Sadegh
12

Jest jedno podejście, które możesz zastosować w swoim przypadku.

Krok 1: Rozpocznij ćwiczenie B od działania A

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

Krok 2: Jeśli użytkownik kliknie przycisk modyfikacji, uruchom działanie A za pomocą FLAG_ACTIVITY_CLEAR_TOP.Also, przekaż flagę dodatkowo.

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

Krok 3: Jeśli użytkownik kliknie przycisk Dodaj, uruchom działanie A za pomocą FLAG_ACTIVITY_CLEAR_TOP.Also, przekaż flagę dodatkowo. FLAG_ACTIVITY_CLEAR_TOPwyczyści wszystkie otwarte działania aż do celu i uruchomi się ponownie, jeśli tryb uruchamiania nie jest zdefiniowany w działaniu docelowym

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

Krok 4: Teraz onCreate()metoda działania A, musisz pobrać tę flagę.

String flag = getIntent().getStringExtra("flag");
if(flag.equals("add")) {
    //Write a code for add
}else {
    //Write a code for modifying
}
Dharmendra
źródło
6

Rozpocznij swoją aktywność od kodu żądania:

StartActivityForResult(intent,1234);

Możesz je zamknąć z dowolnej innej czynności, takiej jak ta:

finishActivity(1234);
yaniv maymon
źródło
W jakim języku??
Morten Holmgaard
5

Zobacz moją odpowiedź na pytanie o przepełnienie stosu Zakończ Wszystkie poprzednie działania .

Musisz dodać rozszerzenie Intent.FLAG_CLEAR_TOP. Ta flaga zapewnia, że ​​wszystkie działania powyżej docelowej aktywności w stosie są zakończone i że jest ona wyświetlana.

Kolejną rzeczą, której potrzebujesz, jest SINGLE_TOPflaga. Dzięki temu zapobiegniesz tworzeniu przez system Android nowego działania, jeśli istnieje już utworzone w stosie.

Uważaj tylko, jeśli działanie zostało już utworzone, intencja z tymi flagami zostanie dostarczona w wywołanej metodzie onNewIntent(intent)(musisz ją przeciążać, aby ją obsłużyć) w działaniu docelowym.

Następnie onNewIntentmasz metodę o nazwie restart lub coś, co wywoła finish()i uruchomi nową intencję wobec siebie, lub ma repopulate()metodę, która ustawi nowe dane. Wolę drugie podejście, jest tańsze i zawsze możesz wyodrębnić onCreatelogikę do oddzielnej metody, którą możesz wywołać w celu wypełnienia.

DArkO
źródło
4

Właśnie zastosowałem rozwiązanie Nepstera i działa jak urok. Istnieje niewielka modyfikacja umożliwiająca uruchomienie go z fragmentu.

Do twojego fragmentu

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

Oraz do OnNewIntent () działania, które chcesz ponownie uruchomić.

// 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);
}
koras
źródło
2

Myślę, że mam najłatwiejsze podejście ... do wciskania nowego w B.

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

iw A weź to

  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);
    }
AndroidGeek
źródło
1

Wiem, że to stare pytanie, kilka z tych metod nie działało w moim przypadku, więc dla każdego, kto patrzy w przyszłość lub ma problemy, zadziałało to dla mnie

Przekonałem onPausei zadzwoniłem finish()do tej metody.

Tony Kutzler
źródło
-1

Najpierw zadzwoń, startactivity()a następnie użyjfinish()

Dharmik Ghori
źródło