setResult nie działa po naciśnięciu przycisku BACK

111

Próbuję ustawić wynik po naciśnięciu przycisku WSTECZ. Wzywam Destroy

Intent data = new Intent();
setResult(RESULT_OK, data) 

Ale jeśli chodzi o

onActivityResult(int requestCode, int resultCode, Intent data) 

resultCode to 0 (RESULT_CANCELED), a dane mają wartość „null”.

Jak więc mogę przekazać wynik z aktywności zakończonej przyciskiem WSTECZ?

alex2k8
źródło

Odpowiedzi:

159

Musisz zmienić onBackPressed()metodę i ustawić wynik przed wywołaniem nadklasy, tj

@Override
public void onBackPressed() {
    Bundle bundle = new Bundle();
    bundle.putString(FIELD_A, mA.getText().toString());
    
    Intent mIntent = new Intent();
    mIntent.putExtras(bundle);
    setResult(RESULT_OK, mIntent);
    super.onBackPressed();
}
n224576
źródło
23
Zwróć uwagę, że jeśli użyjesz tego podejścia, wywołanie super.onBackPressed () musi nastąpić po wywołaniu setResult (), jak pokazano powyżej, w przeciwnym razie będziesz miał ponownie pierwotny problem!
jengelsma
1
To najlepsza odpowiedź tutaj. Jeśli nadpisujemy onPause () lub onDestroy (), onBackPressed () zostanie wywołany jako pierwszy i ustawi wynik na 0. Należy o tym pamiętać!
Marek,
lub możesz ustawić domyślny wynik w onCreate. Każde miejsce przed finish () jest w porządku.
Helin Wang
5
Wdrożyłem podobne podejście, ale nadal nie działa. Dla instancji mam kod żądania i intencję, ale kod wyniku jest zawsze równy 0.
Neon Warge
68

Activitywynik musi być ustawiony przed finish() wywołaniem. Kliknięcie WSTECZ faktycznie wywołuje finish()Twój activity, więc możesz użyć następującego fragmentu:

@Override
public void finish() {
    Intent data = new Intent();
    setResult(RESULT_OK, data); 

    super.finish();
}

Jeśli nazywasz NavUtils.navigateUpFromSameTask();się onOptionsItemSelected(), finish()nazywa, ale dostaniesz złym result code. Więc trzeba nazwać finish()nie navigateUpFromSameTaskw onOptionsItemSelected(). zły requestCode w onActivityResult

JBM
źródło
Działa to w przypadku PO, ale nie ogólnie, prawda? Istnieje więcej metod niż finish (), które powodują koniec cyklu życia aplikacji (poprzez onPause () i onDestroy ())? Zobacz także mój komentarz przy innej odpowiedzi.
pjv
A nawet gdyby nie było, nie wiedziałbyś o tym, kiedy zostałby wprowadzony w aktualizacji API. Nie tak łatwo, jak gdyby zmieniło się zachowanie onPause () lub onDestroy (). To są metody, które powinieneś zastąpić.
pjv
6
@pjv - nie rozumiem, co finishma wspólnego z onPausei onDestroy? Te są całkowicie niezwiązane, z wyjątkiem tego, że finishrozpoczyna proces zakończenia, który onPausei onDestroyjest częścią.
JBM
20

Jeśli chcesz ustawić niestandardowe RESULT_CODEw onBackPressedzdarzeniu, musisz najpierw ustawić, resulta następnie wywołać, super.onBackPressed()a otrzymasz to samo RESULT_CODEw onActivityResultmetodzie działania dzwoniącego

    @Override
    public void onBackPressed()
    {
         setResult(SOME_INTEGER);
         super.onBackPressed();
    }
Khurram Shehzad
źródło
10

Zrefaktorowałem mój kod. Początkowo przygotowałem dane i ustawiłem jak activity resultw onDestroy(to nie zadziałało). Teraz ustawiam activitydane za każdym razem, gdy dane, które mają zostać zwrócone, są aktualizowane i nie mam w nich nic onDestroy.

alex2k8
źródło
U mnie to nie działa, ponieważ moje dane są aktualizowane w trybie „onPause”
Bostone,
Jeśli Twoja aktywność zostanie odtworzona po połączeniu setResult(), Twoje dane zostaną utracone.
Jarett Millard
3

Należy nadpisać onOptionsItemSelected w następujący sposób:

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        final Intent mIntent = new Intent();
        mIntent.putExtra("param", "value");
        setResult(RESULT_OK, mIntent);
        finish();
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}
mdolanci
źródło
2

Refer onActivityResult (int, int, Intent) doc

Rozwiązaniem jest sprawdzenie resultCode dla wartości Activity.RESULT_CENCELED . Jeśli tak, oznacza to, że naciśnięto przycisk BACK lub działanie się zawiesiło. Mam nadzieję, że to działa dla was, działa dla mnie :).

Ankur
źródło
To jest dokładne rozwiązanie .. Musisz kod wyniku .. Nikt nie może ustawić wyniku w kodzie poza tobą. Tak więc, jeśli wynik nie jest OK, oznacza to, że albo naciska wstecz, albo się rozbił ...
Jan
0

onDestroyjest za późno w łańcuchu - zamiast tego zastąp onPausei isFinishing()sprawdź, czy Twoja aktywność zbliża się do końca swojego cyklu życia.

Roman Nurik
źródło
1
Nie, to też jest za późno.
alex2k8
Właściwie nazywam to błędem: code.google.com/p/android/issues/detail?id=1671 . W złożonych aplikacjach myślę, że z tego powodu istnieje pewne zachowanie, którego nie można zaprogramować.
pjv
Jest to również bardzo sprzeczne z intuicją. Tak bardzo, że ciągle popełniam ten sam błąd, już od 2 lat.
pjv
Właściwie - to jest jeszcze gorsze. I istnieje w JB, gdy koduję. Jeśli wywołuję setResult z onPause, jest on wykonywany, ale po wykonaniu onActivityReturn nie jest ustawiany kod wyniku ani dane. Czemu?
Bostone
I dlatego: „Implementacja tej metody (onPause) musi być bardzo szybka, ponieważ następne działanie nie zostanie wznowione, dopóki ta metoda nie zwróci” goo.gl/8S2Y
Bostone
0

Spróbuj zastąpić onBackPressed (od poziomu Androida 5 w górę) lub przesłonić onKeyDown () i przechwycić KeyEvent.BUTTON_BACK (zobacz Wyniki aktywności Androida ) To załatwia sprawę .

MrJre
źródło
0

Nie polegaj na żadnej logice wykonywanej w onPause jednej czynności, gdy powrócisz do pierwotnej. Według dokumentów:

Implementacje tej metody (onPause) muszą być bardzo szybkie, ponieważ następne działanie nie zostanie wznowione, dopóki ta metoda nie zwróci

Szczegółowe informacje można znaleźć pod adresem http://goo.gl/8S2Y .

Najbezpieczniejszym sposobem jest ustawienie wyniku po zakończeniu każdej operacji zmiany wyniku (jak wspomniałeś w swojej odpowiedzi)

Bostone
źródło
0

wklejam odpowiedź może być pomocna dla innych osób: kiedy ustawię launcheMode z androidem: launchMode = "singleTask", również nie mogę uzyskać wyniku, dokument mówi:

     /* <p>Note that this method should only be used with Intent protocols
 * that are defined to return a result.  In other protocols (such as
 * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
 * not get the result when you expect.  For example, if the activity you
 * are launching uses the singleTask launch mode, it will not run in your
 * task and thus you will immediately receive a cancel result.
 */

i:

     /* <p>As a special case, if you call startActivityForResult() with a requestCode 
 * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
 * activity, then your window will not be displayed until a result is 
 * returned back from the started activity.  This is to avoid visible 
 * flickering when redirecting to another activity. 
 */
banxi1988
źródło