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.