setResult no funciona cuando se presiona el botón BACK

111

Estoy tratando de establecer el resultado después de presionar el botón ATRÁS. Llamo a Destroy

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

Pero cuando se trata de

onActivityResult(int requestCode, int resultCode, Intent data) 

el resultCode es 0 (RESULT_CANCELED) y los datos son 'nulos'.

Entonces, ¿cómo puedo pasar el resultado de la actividad terminada por el botón ATRÁS?

alex2k8
fuente

Respuestas:

159

Debe anular el onBackPressed()método y establecer el resultado antes de la llamada a superclase, es decir

@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
fuente
23
Tenga en cuenta que si usa este enfoque, la invocación super.onBackPressed () debe ocurrir después de la llamada a setResult () como se muestra arriba o ¡tendrá el problema original nuevamente!
jengelsma
1
Esa es la mejor respuesta aquí. Si anulamos onPause () o onDestroy (), onBackPressed () se llamará primero y establecerá el resultado en 0. ¡Tenga en cuenta eso!
Marek
o puede establecer el resultado predeterminado en onCreate. Cualquier lugar antes de terminar () está bien.
Helin Wang
5
Implementé un enfoque similar pero todavía no funciona. Por ejemplo, tengo el código de solicitud y la intención en funcionamiento, pero el código de resultado es siempre 0.
Neon Warge
68

ActivityEl resultado debe establecerse antes de que finish() se llame. Al hacer clic en ATRÁS, en realidad se llama finish()a su activity, por lo que puede usar el siguiente fragmento:

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

    super.finish();
}

Si llama NavUtils.navigateUpFromSameTask();en onOptionsItemSelected(), finish()que se llama, pero obtendrá el mal result code. Así que hay que llamar finish(), no navigateUpFromSameTasken onOptionsItemSelected(). requestCode incorrecto en onActivityResult

JBM
fuente
Esto funciona en el caso de los OP, pero no en general, ¿verdad? ¿Hay más métodos además de finish () que inducen el final del ciclo de vida de la aplicación (a través de onPause () y onDestroy ())? También vea mi comentario en la otra respuesta.
pjv
E incluso si no lo hubiera, no lo sabría cuando se presentaría en una actualización de API. No tan fácilmente como lo haría cuando cambia el comportamiento de onPause () o onDestroy (). Esos son los métodos que se supone que debe anular.
pjv
6
@pjv - No entiendo tu punto, ¿qué finishtiene que ver con onPausey onDestroy? Aquellos totalmente de que no están relacionados a excepción de que finishse inicia el proceso de terminación que onPausey onDestroyson parte de.
JBM
20

Si desea establecer alguna costumbre RESULT_CODEen el onBackPressedcaso entonces usted necesita para el primer set resulty luego llamar al super.onBackPressed()y recibirá el mismo RESULT_CODEen la actividad de la persona que llama onActivityResultmétodo

    @Override
    public void onBackPressed()
    {
         setResult(SOME_INTEGER);
         super.onBackPressed();
    }
Khurram Shehzad
fuente
10

Refactoré mi código. Inicialmente preparé algunos datos y los configuré como activity resulten onDestroy(esto no funcionó). Ahora configuro activitydatos cada vez que se actualizan los datos que se devolverán y no tengo nada en onDestroy.

alex2k8
fuente
Esto no me funciona ya que mis datos se actualizan en "onPause"
Bostone
Si su actividad se vuelve a crear después de llamar setResult(), sus datos se perderán.
Jarett Millard
3

Debe anular onOptionsItemSelected así:

@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
fuente
2

Consulte el documento de onActivityResult (int, int, Intent)

La solución es verificar el valor de resultCode Activity.RESULT_CENCELED . Si es así, significa que se presionó ATRÁS o la actividad se bloqueó. Espero que les funcione a ustedes, a mí me funciona :).

Ankur
fuente
Esta es la solución exacta .. Tienes que Código de resultado .. Nadie puede establecer el resultado excepto tú en el código. Por lo tanto, si el resultado no es correcto, significa que se presionó hacia atrás o se estrelló.
John
0

onDestroyes demasiado tarde en la cadena; en su lugar, anule onPausey isFinishing()verifique si su actividad está al final de su ciclo de vida.

Roman Nurik
fuente
1
No, esto también es demasiado tarde.
alex2k8
De hecho, llamo a esto un error: code.google.com/p/android/issues/detail?id=1671 . En aplicaciones complejas, creo que debido a esto, hay un comportamiento que no se puede programar.
pjv
También es muy contrario a la intuición. Tanto que sigo cometiendo el mismo error, durante un período de 2 años.
pjv
En realidad, esto es aún peor. Y existe en JB mientras estoy codificando. Si llamo a setResult desde onPause, se ejecuta pero ni resultCode ni datos se establecen cuando se ejecuta onActivityReturn. ¿Por qué?
Bostone
Y es por eso: "Las implementaciones de este método (onPause) deben ser muy rápidas porque la siguiente actividad no se reanudará hasta que este método devuelva" goo.gl/8S2Y
Bostone
0

No confíe en ninguna lógica ejecutada en onPause de una actividad cuando regrese a la inicial. Según los documentos:

Las implementaciones de este método (onPause) deben ser muy rápidas porque la siguiente actividad no se reanudará hasta que este método regrese

Consulte http://goo.gl/8S2Y para obtener más detalles.

La forma más segura es establecer el resultado después de que se complete cada operación de modificación de resultados (como menciona en su respuesta)

Bostone
fuente
0

pego la respuesta puede ser útil para otras personas: cuando un launcheMode configurado con android: launchMode = "singleTask" tampoco puedo obtener el resultado, el 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.
 */

y:

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