Regresando de una actividad usando navigateUpFromSameTask ()

Tengo dos actividades, A y B. Cuando se inicia la actividad A, accede a la Intent pasada a ella (porque el Bundle es null , como debería ser la primera vez) y muestra la información en consecuencia:

 CustInfo m_custInfo; ... protected void onCreate(Bundle savedInstanceState) { ... Bundle bundle = (savedInstanceState == null) ? getIntent().getExtras() : savedInstanceState; m_custInfo = (CustInfo) m_bundle.getSerializable("CustInfo"); if (m_custInfo != null ... } 

Esto funciona bien la primera vez. Los controles EditText y ListView se rellenan correctamente.

Ahora, cuando se hace clic en un elemento de la lista, se inicia la actividad B para mostrar los detalles:

 m_custInfo = m_arrCustomers.get(pos); Intent intent = new Intent(A.this, B.class); intent.putExtra("CustInfo", m_custInfo); // CustInfo is serializable // printing this intent, it shows to have extras and no flags startActivityForResult(intent, 1); 

Justo antes de iniciar la actividad B, el framework llama a A sobreescrito onSaveInstanceState() :

 protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putSerializable("CustInfo", m_custInfo); } 

En la actividad B, cuando se presiona el botón Arriba en la barra de acción, quiero volver a la actividad A y tenerla en el mismo estado en que estaba antes:

 public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { Intent intent = NavUtils.getParentActivityIntent(this); // printing this intent, it shows to have flags but no extras NavUtils.navigateUpFromSameTask(this); // tried finish() here but that created an even bigger mess return true; } ... } 

Aquí reside el problema, cuando en onCreate() de la actividad A la segunda vez, el parámetro Bundle es null y getExtras() devuelve null . Desde que se llamó onSaveInstanceState() , habría esperado que el parámetro Bundle fuera no null .

He leído sobre este tema en otros sitios web, he probado las sugerencias, pero nada funciona.

Si desea que su aplicación reaccione de esta manera, debe declarar el modo de inicio de su actividad A como:

 android:launchMode="singleTop" 

En su AndroidManifest.xml.

De lo contrario, Android utiliza el modo de inicio estándar, lo que significa

"El sistema siempre crea una nueva instancia de la actividad en la tarea de destino"

Y su actividad se ha recreado (consulte la documentación de Android ).

Con singleTop el sistema vuelve a su actividad existente (con el extra original), si está en la parte superior de la pila trasera de la tarea. No es necesario implementar onSaveInstanceState en esta situación.

SavedInstanceState es nulo en su caso, porque su actividad no estaba siendo cerrada por el sistema operativo anteriormente.

Aviso (gracias, desarrollador android por señalar esto ) :

Si bien esta es una solución a la pregunta, no funcionará si la actividad a la que se devuelve no está en la parte superior de la pila trasera. Considere el caso de la actividad A iniciando B, que está iniciando C, y la actividad principal de C está configurada para ser A. Si llama a NavigateUpFromSameTask() desde C, la actividad se recreará, porque A no está en la parte superior de la pila.

En este caso uno puede usar este pedazo de código en su lugar:

 Intent intent = NavUtils.getParentActivityIntent(this); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP); NavUtils.navigateUpTo(this, intent); 

Esto sucede porque NavUtils.navigateUpFromSameTask() básicamente sólo llama startActivity(intentForActivityA) . Si la actividad A usa el android:launchMode="standard" defecto android:launchMode="standard" entonces se crea una nueva instancia de la actividad y no se usa el estado guardado. Hay tres maneras de arreglar esto, con varias ventajas y desventajas.

Opción 1

Anule getParentActivityIntent () en la actividad B y especifique los extras adecuados necesarios para la actividad A:

 @Override public Intent getParentActivityIntent() { Intent intent = super.getParentActivityIntent(); intent.putSerializable("CustInfo", m_custInfo); return intent; } 

Nota: Si está utilizando ActionBarActivity y la barra de herramientas de la biblioteca de soporte, deberá sustituir getSupportParentActivityIntent () .

Creo que esta es la solución más elegante ya que funciona independientemente de cómo el usuario navegó a la actividad B. Las dos opciones que se enumeran a continuación no funcionan correctamente si el usuario navega directamente a la actividad B sin pasar por la actividad A, por ejemplo, si la actividad B se inicia desde un controlador de notificación o URL. Creo que este escenario es la razón por la "arriba" de navegación API es complicado y no simplemente actuar como un mudo botón de nuevo.

Un inconveniente de esta solución es que se utiliza la animación de transición de inicio de una actividad nueva estándar en lugar de la animación de actividad de retorno a anterior.

opcion 2

Interceptar el botón de arriba y tratarlo como un botón de mudo de nuevo por sobreescribir onNavigateUp () :

 @Override public boolean onNavigateUp() { onBackPressed(); return true; } 

Nota: Si está utilizando ActionBarActivity y la barra de herramientas de la biblioteca de soporte, deberá sustituir onSupportNavigateUp () .

Una ventaja de esta solución es que se utiliza la animación estándar de retorno a actividad anterior.

Opción 3

Como sugiere yonojoy, defina android:launchMode="singleTop" en la actividad A. Vea su respuesta para más detalles. Tenga en cuenta que singleTop no es apropiado para todas las aplicaciones. Tendrás que probarlo y / o pasar algún tiempo leyendo la documentación para decidir por ti mismo.

En lugar de llamar a NavUtils.navigateUpFromSameTask

Puede obtener la intención de los padres y modificarla antes de navegar. Por ejemplo:

 Intent intent = NavUtils.getParentActivityIntent(this); intent.putExtra("CustInfo", m_custInfo); // CustInfo is serializable NavUtils.navigateUpTo(this, intent); 

Esto se comportará exactamente igual que NavUtils.navigateUpFromSameTask pero le permitirá agregar algunas propiedades adicionales a la intención. Puedes echar un vistazo al código de NavUtils.navigateUpFromSameTask es muy simple.

 public static void navigateUpFromSameTask(Activity sourceActivity) { Intent upIntent = getParentActivityIntent(sourceActivity); if (upIntent == null) { throw new IllegalArgumentException("Activity " + sourceActivity.getClass().getSimpleName() + " does not have a parent activity name specified." + " (Did you forget to add the android.support.PARENT_ACTIVITY <meta-data> " + " element in your manifest?)"); } navigateUpTo(sourceActivity, upIntent); } 

Hacer la actividad de los padres SINGLE_TOP puede funcionar para algunas aplicaciones sencillas, pero ¿y si esta actividad no se inició directamente desde su padre? O puede legítimamente querer que el padre exista en varios lugares en la pila trasera.

Mencionas:

En la actividad B, cuando se pulsa el botón Arriba en la barra de acción, quiero volver a la actividad A y tenerla en el mismo estado en que estaba antes.

Si el contenido de la Actividad A reside en un Fragmento, entonces llame a setRetainInstance (true) en el onCreate () del Fragmento.

A continuación, la instancia de Fragmento se mantendrá en Recreación de actividad.

  • StartActivity creando nueva instancia de Activity cada vez
  • Actividad que no se cierra en Back press cuando tema es Theme.NoDisplay
  • ¿Presionando Atrás siempre causa Actividad para finalizar ()?
  • Animación de transición de actividad de izquierda a derecha en Android
  • ¿PreferenceFragment con el fondo transparente?
  • No se destruye la actividad actual al pulsar el botón Atrás
  • Android Fragment onCreateView vs. onActivityCreated
  • Cómo cerrar la actividad y volver a la actividad anterior en android
  • Cómo hacer HorizontalScrollView RIGHT a LEFT Scroll android
  • ¿Cómo reinicio una actividad de Android?
  • Comprensión onTrimMemory (nivel int)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.