setResult non funziona quando si preme il pulsante BACK


111

Sto tentando di impostare il risultato dopo aver premuto il pulsante INDIETRO. Chiamo onDestroy

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

Ma quando si tratta di

onActivityResult(int requestCode, int resultCode, Intent data) 

il resultCode è 0 (RESULT_CANCELED) e i dati sono "null".

Quindi, come posso passare il risultato di un'attività terminata dal pulsante INDIETRO?

Risposte:


159

È necessario sovrascrivere il onBackPressed()metodo e impostare il risultato prima della chiamata alla superclasse, ad es

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

23
Nota che se usi questo approccio l'invocazione super.onBackPressed () deve avvenire dopo la chiamata a setResult () come mostrato sopra o avrai di nuovo il problema originale!
jengelsma

1
Questa è la migliore risposta qui. Se sovrascriviamo onPause () o onDestroy (), onBackPressed () verrà chiamato per primo e imposterà il risultato a 0. Si prega di essere consapevoli di questo!
Marek

oppure puoi impostare il risultato predefinito in onCreate. Qualsiasi posto prima di finish () va bene.
Helin Wang,

5
Ho implementato un approccio simile ma ancora non funziona. Per l'istanza ho il codice della richiesta e l'intento funzionante, ma il codice del risultato è sempre 0.
Neon Warge

68

ActivityIl risultato deve essere impostato prima di finish() essere chiamato. Facendo clic su INDIETRO si chiama effettivamente finish()il tuo activity, quindi puoi utilizzare il seguente frammento:

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

    super.finish();
}

Se si chiama NavUtils.navigateUpFromSameTask();in onOptionsItemSelected(), finish()si chiama, ma si otterrà lo sbagliata result code. Quindi devi chiamare finish(), non navigateUpFromSameTaskin onOptionsItemSelected(). requestCode errata in onActivityResult


Funziona nel caso degli OP, ma non in generale, giusto? Esistono più metodi oltre a finish () che inducono la fine del ciclo di vita dell'app (tramite onPause () e onDestroy ())? Vedi anche il mio commento all'altra risposta.
pjv

E anche se non ci fossero, non lo sapresti quando verrebbe introdotto in un aggiornamento API. Non così facilmente come faresti quando il comportamento di onPause () o onDestroy () è cambiato. Questi sono i metodi che dovresti ignorare.
pjv

6
@pjv - Non capisco il tuo punto, cosa finishha a che fare con onPausee onDestroy? Quelli sono totalmente non correlati tranne che per l' finishavvio del processo di risoluzione di cui onPausee onDestroyfanno parte.
JBM

20

Se si desidera impostare un po 'personalizzato RESULT_CODEin onBackPressedcaso allora avete bisogno di prima serie del resulte quindi chiamare il super.onBackPressed()e riceverai lo stesso RESULT_CODEnella propria attività chiamante onActivityResultmetodo

    @Override
    public void onBackPressed()
    {
         setResult(SOME_INTEGER);
         super.onBackPressed();
    }

10

Ho riformattato il mio codice. Inizialmente ho preparato alcuni dati e l'ho impostato come activity resultin onDestroy(questo non ha funzionato). Ora imposto i activitydati ogni volta che i dati da restituire vengono aggiornati e non ho nulla in onDestroy.


Questo non funziona per me perché i miei dati sono in aggiornamento "onPause"
Bostone

Se la tua attività viene ricreata dopo la chiamata setResult(), i tuoi dati andranno persi.
Jarett Millard

3

Dovresti sovrascrivere onOptionsItemSelected in questo modo:

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

2

Fare riferimento al documento onActivityResult (int, int, Intent)

La soluzione è controllare il resultCode per il valore Activity.RESULT_CENCELED . Se sì, significa che è stato premuto BACK o l'attività si è bloccata. Spero che funzioni per voi ragazzi, funziona per me :).


Questa è la soluzione esatta .. Devi Codice risultato .. Nessuno può impostare il risultato diverso da te nel codice. Quindi, se il risultato non è OK significa che il suo back press o si è schiantato ..
John

0

onDestroyè troppo tardi nella catena: sostituisci onPausee isFinishing()controlla se la tua attività è alla fine del suo ciclo di vita.


1
No, anche questo è troppo tardi.
alex2k8

In realtà lo chiamo un bug: code.google.com/p/android/issues/detail?id=1671 . In applicazioni complesse penso che a causa di ciò ci sia solo un comportamento che non puoi programmare.
pjv

È anche molto controintuitivo. Tanto che continuo a fare lo stesso errore, già da 2 anni.
pjv

In realtà, questo è anche peggio. Ed esiste in JB mentre sto codificando. Se chiamo setResult da onPause viene eseguito ma nether resultCode né data viene impostato quando viene eseguito onActivityReturn. Perché?
Bostone

Ed è per questo: "Le implementazioni di questo metodo (onPause) deve essere molto veloce perché la prossima attività non riprenderà fino a quando questo metodo restituisce" goo.gl/8S2Y
Bostone

0

Prova a sovrascrivere onBackPressed (dal livello Android 5 in su) o sovrascrivi onKeyDown () e prendi KeyEvent.BUTTON_BACK (vedi Risultati attività Android ) Questo fa il trucco per me.


0

Non fare affidamento su alcuna logica eseguita in onPause of one quando torni a quella iniziale. Secondo i documenti:

Le implementazioni di questo metodo (onPause) devono essere molto veloci perché l'attività successiva non verrà ripresa finché questo metodo non ritorna

Vedere http://goo.gl/8S2Y per i dettagli.

Il modo più sicuro è impostare il risultato dopo che ogni operazione di modifica del risultato è stata completata (come hai menzionato nella tua risposta)


0

incollo la risposta potrebbe essere utile ad altre persone: quando un set launcheMode con android: launchMode = "singleTask" non riesco nemmeno a ottenere il risultato, il documento dice:

     /* <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.
 */

e:

     /* <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. 
 */
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.