setResult non funziona quando il pulsante BACK è premuto


90

Sto tentando di impostareRisultato dopo aver premuto il pulsante BACK. Chiamo in 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 dati sono 'null'.

Quindi, come posso passare il risultato dell'attività interrotta dal pulsante BACK?

9

Ho rifattorizzato il mio codice. Inizialmente ho preparato alcuni dati e l'ho impostato come activity result in onDestroy (questo non ha funzionato). Ora ho impostato i dati activity ogni volta che i dati da restituire sono aggiornati e non contengono nulla in onDestroy.

  0

Questo non funziona per me dato che i miei dati sono aggiornamento in "onPause" 22 lug. 122012-07-22 17:49:53

  0

Se la tua attività viene ricreata dopo aver chiamato 'setResult()', i tuoi dati andranno persi. 12 mag. 162016-05-12 13:40:41


0

onDestroy è troppo tardi nella catena — invece ignorare e controllare isFinishing() per controllare se la vostra attività è alla fine del suo ciclo di vita.

+1

No, è troppo tardi. 22 apr. 102010-04-22 03:01:15

+1

Oh, whoops .. :) 22 apr. 102010-04-22 04:39:11

  0

In realtà lo chiamo un bug: http://code.google.com/p/android/issues/detail?id=1671. In applicazioni complesse penso che a causa di questo ci sia solo un comportamento che non puoi programmare. 16 mar. 112011-03-16 22:21:54

  0

È anche molto controintuitivo. Tanto che continuo a fare lo stesso errore, già in un periodo di 2 anni. 16 mar. 112011-03-16 22:28:31

  0

In realtà - questo è ancora peggio. Ed esiste in JB come sto codificando. Se chiamo setResult da onPause viene eseguito ma nè resultCode né dati vengono impostati quando onActivityReturn viene eseguito. Perché? 22 lug. 122012-07-22 17:49:20

  0

Ed ecco perché: "Le implementazioni di questo metodo (onPause) devono essere molto veloci perché la prossima attività non sarà ripresa fino a quando questo metodo non ritorna" http://goo.gl/8S2Y 22 lug. 122012-07-22 17:52:47


56

Activity il risultato deve essere impostato prima delfinish() viene chiamato. Facendo clic su Indietro chiama in realtà finish() sul activity, in modo da poter 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à il torto result code. Quindi devi chiamare finish() non navigateUpFromSameTask in onOptionsItemSelected(). wrong requestCode in onActivityResult

  0

Questo funziona nel caso degli OP, ma non in generale, giusto? Esistono più metodi di finish() che inducono la fine del ciclo di vita dell'app (tramite onPause() e onDestroy())? Vedi anche il mio commento all'altra risposta. 16 mar. 112011-03-16 22:24:08

  0

E anche se non ce ne fossero, non lo sapresti quando verrà introdotto in un aggiornamento API. Non con la stessa facilità con cui si modificano i comportamenti di onPause() o onDestroy(). Questi sono i metodi che * dovresti * scavalcare. 16 mar. 112011-03-16 22:31:58

+5

@pjv - Non capisco il tuo punto, cosa 'finish' ha a che fare con' onPause' e ​​'onDestroy'? Quelli sono totalmente non correlati eccetto che il 'finish' inizia il processo di terminazione a cui fanno parte' onPause' e ​​'onDestroy'. 30 ago. 112011-08-30 19:45:13


3

consultare onActivityResult(int, int, Intent) doc

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

  0

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 viene premuto Indietro o 01. Crollato. 15 set. 152015-09-15 14:16:26


0

Prova sovrascrivendo onBackPressed (da Android livello 5 in su), o ignorare onKeyDown() e prendere KeyEvent.BUTTON_BACK (vedi Android Activity Results) Questo fa il trucco per me.


128

È necessario overide il metodo onBackPressed() e impostare il risultato prima della chiamata a superclasse, cioè

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

Nota che se si utilizza questo approccio, il richiamo di super.onBackPressed() deve avvenire dopo la chiamata a setResult() come mostrato sopra o si avrà l'originale problema tutto da capo! 24 mag. 122012-05-24 18:28:43

+1

Questa è la migliore risposta qui. Se sostituiamo onPause() o onDestroy(), onBackPressed() verrà chiamato per primo e imposterà il risultato su 0. Si prega di essere consapevoli di ciò! 05 lug. 132013-07-05 05:02:13

  0

oppure è possibile impostare il risultato predefinito su onCreate. Qualsiasi posto prima della fine() va bene. 26 set. 132013-09-26 15:35:03

+4

Ho implementato un approccio simile ma ancora non funziona. Per esempio ho il codice di richiesta e l'intento funziona ma il risultato è sempre 0. 30 apr. 152015-04-30 14:35:19


0

non si basano su alcuna logica eseguita in onPause di un'attività quando si torna a quella iniziale uno. Secondo la documentazione:

Le implementazioni di questo metodo (onPause) deve essere molto veloce perché la prossima attività non riprenderà fino a quando questo metodo restituisce

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

Il modo più sicuro è quello di impostare risultato dopo ogni operazione risultato alterazione è completo (come si parla nella sua risposta)


2

Si dovrebbe ignorare onOptionsItemSelected come questo:

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

0

incollo la risposta potrebbe essere utile ad altre persone: quando un insieme launcheMode con android: launchMode = "singleTask" non riesco 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. 
*/ 

13

Se si desidera impostare un po 'personalizzato RESULT_CODE in onBackPressed evento, allora è necessario impostare prima il result e quindi chiamare il super.onBackPressed() e riceverai la stessa RESULT_CODE in di l'attività chiamante onActivityResult metodo

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