Conceptos básicos de Android 2.2: Estado y ciclo de vida de la actividad

1. Te damos la bienvenida

Introducción

En esta práctica, obtendrás más información sobre el ciclo de vida de la actividad. El ciclo de vida es el conjunto de estados que puede tener una actividad durante toda su vida útil, desde que se crea hasta que se destruye y el sistema recupera sus recursos. A medida que un usuario navega entre las actividades de tu app (y también cuando ingresa a la app y sale de ella), las actividades pasan por diferentes estados en sus ciclos de vida.

Diagrama del ciclo de vida de la app

Cada etapa del ciclo de vida de una actividad tiene un método de devolución de llamada correspondiente: onCreate(), onStart(), onPause(), etc. Cuando una actividad cambia de estado, se invoca el método de devolución de llamada asociado. Ya viste uno de estos métodos: onCreate(). Si anulas cualquiera de los métodos de devolución de llamada de ciclo de vida en tus clases Activity, puedes cambiar el comportamiento predeterminado de la actividad en respuesta a las acciones del usuario o del sistema.

El estado de la actividad también puede cambiar en respuesta a los cambios de configuración del dispositivo, por ejemplo, cuando el usuario rota el dispositivo de la posición vertical a la horizontal. Cuando se producen estos cambios de configuración, la actividad se destruye y se vuelve a crear en su estado predeterminado. Como resultado, el usuario puede perder la información que ingresó en la actividad. Para evitar confundir a los usuarios, es importante que desarrolles tu app con el objetivo de evitar pérdidas de datos inesperadas. Más adelante en esta práctica, experimentarás con los cambios de configuración y aprenderás a preservar el estado de una actividad en respuesta a los cambios en la configuración del dispositivo y otros eventos de ciclo de vida de la actividad.

En esta práctica, agregarás instrucciones de registro a la app de TwoActivities y observarás cambios en el ciclo de vida de la actividad a medida que la usas. Luego, comenzarás a trabajar con estos cambios y a explorar cómo manejar las entradas del usuario en estas condiciones.

Conocimientos que ya deberías tener

Deberías ser capaz de hacer lo siguiente:

  • Crear y ejecutar un proyecto de app en Android Studio
  • Agregar instrucciones de registro a tu app y observar esos registros en el panel Logcat
  • Interpretar y trabajar con Activity y Intent, y haber interactuando con ellos

Qué aprenderás

  • Cómo funciona el ciclo de vida de Activity
  • Cuándo se inicia, se pausa, se detiene y se destruye un Activity
  • Los métodos de devolución de llamada de ciclo de vida asociados con los cambios de Activity
  • El efecto de las acciones (como los cambios de configuración) que pueden generar eventos del ciclo de vida de Activity
  • Cómo retener el estado Activity en eventos de ciclo de vida

Actividades

  • Agrega código a la app de TwoActivities de la práctica anterior para implementar las diversas devoluciones de llamada de ciclo de vida de Activity e incluir instrucciones de registro.
  • Observa los cambios de estado a medida que se ejecuta tu app y a medida que interactúas con cada Activity en ella.
  • Modifica tu app para conservar el estado de la instancia de una Activity que se vuelve a crear de forma inesperada en respuesta al comportamiento del usuario o al cambio de configuración en el dispositivo.

2. Descripción general de la app

En esta práctica, agregarás la app a TwoActivities. La app se ve y se comporta casi de la misma manera que en el último codelab. Contiene dos implementaciones Activity y permite al usuario enviar archivos entre ellas. Los cambios que realices en la app en esta práctica no afectarán su comportamiento visible.

3. Tarea 1: Agrega devoluciones de llamada de ciclo de vida a TwoActivities

En esta tarea, implementarás todos los métodos de devolución de llamada de ciclo de vida de Activity para imprimir mensajes en logcat cuando se invoquen esos métodos. Estos mensajes de registro te permitirán ver cuándo cambia el estado del ciclo de vida de Activity y cómo afectan esos cambios del ciclo de vida a tu app mientras se ejecuta.

1.1 (Opcional) Copia el proyecto TwoActivities

Para las tareas de esta práctica, modificarás el proyecto existente TwoActivities que compilaste en la última práctica. Si prefieres no modificar el proyecto TwoActivities anterior, sigue los pasos indicados en el Apéndice: Utilidades para realizar una copia del proyecto.

1.2 Implementa devoluciones de llamada en MainActivity

  1. Abre el proyecto TwoActivities en Android Studio y abre MainActivity en el panel Project > Android.
  2. En el método onCreate(), agrega las siguientes instrucciones de registro:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Agrega una anulación para la devolución de llamada de onStart(), con una sentencia en el registro de ese evento:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Para obtener un acceso directo, selecciona Code > Override Methods en Android Studio. Aparecerá un diálogo con todos los métodos posibles que puedes anular en tu clase. Si eliges uno o más métodos de devolución de llamada de la lista, se inserta una plantilla completa para esos métodos, incluida la llamada necesaria a la superclase.

  1. Usa el método onStart() como plantilla para implementar las devoluciones de llamada de ciclo de vida onPause(), onRestart(), onResume(), onStop() y onDestroy().

Todos los métodos de devolución de llamada tienen las mismas firmas (excepto el nombre). Si copias y pegas onStart() para crear estos otros métodos de devolución de llamada, no olvides actualizar el contenido para llamar al método correcto en la superclase y registrar el método correcto.

  1. Ejecuta tu app.
  2. Haz clic en la pestaña Logcat en la parte inferior de Android Studio para mostrar el panel de Logcat. Deberías ver tres mensajes de registro que muestran los tres estados del ciclo de vida por los que pasó Activity durante desde inicio:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementa devoluciones de llamada de ciclo de vida en SecondActivity

Ahora que implementaste los métodos de devolución de llamada de ciclo de vida para MainActivity, haz lo mismo con SecondActivity.

  1. Abre SecondActivity.
  2. En la parte superior de la clase, agrega una constante para la variable LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Agrega las devoluciones de llamada de ciclo de vida y las instrucciones de registro a la segunda Activity. Puedes copiar y pegar los métodos de devolución de llamada de MainActivity.
  2. Agrega una instrucción de registro al método returnReply() justo antes del método finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Observa de los registros mientras se ejecuta la app

  1. Ejecuta tu app.
  2. Haz clic en la pestaña Logcat en la parte inferior de Android Studio para mostrar el panel de Logcat.
  3. Ingresa Actividad en el cuadro de búsqueda. El logcat de Android puede ser muy largo y desordenado. Debido a que la variable LOG_TAG de cada clase contiene las palabras MainActivity o SecondActivity, esta palabra clave te permite filtrar el registro solo para las cosas que te interesan.

Registro que muestra los estados del ciclo de vida

Experimenta con la app y observa los eventos de ciclo de vida que tienen lugar en respuesta a diferentes acciones. En particular, prueba lo siguiente:

  • Usa la app normalmente (envía un mensaje y responde con otro mensaje).
  • Usa el botón Atrás para volver del segundo Activity al Activity principal.
  • Usa la flecha hacia arriba en la barra de la aplicación para volver del segundo Activity al Activity principal.
  • Rota el dispositivo a la Activity principal y secundaria en diferentes momentos de tu app y observa lo que sucede en el registro y en la pantalla.
  • Presiona el botón Recientes (el botón cuadrado que se encuentra a la derecha de Inicio) y cierra la app (presiona la X).
  • Regresa a la pantalla principal y reinicia la app.

NOTA: Si ejecutas tu app en un emulador, puedes simular la rotación con Control+F11 o Control+Function+F11.

Código de solución de la tarea 1

En los siguientes fragmentos de código, se muestra el código de solución para la primera tarea.

MainActivity

Los siguientes fragmentos de código muestran el código agregado en MainActivity, pero no toda la clase.

El método onCreate().

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Log the start of the onCreate() method.
        Log.d(LOG_TAG, "-------");
        Log.d(LOG_TAG, "onCreate");

        // Initialize all the view variables.
        mMessageEditText = findViewById(R.id.editText_main);
        mReplyHeadTextView = findViewById(R.id.text_header_reply);
        mReplyTextView = findViewById(R.id.text_message_reply);
}

Los otros métodos del ciclo de vida:

@Override
protected void onStart() {
        super.onStart();
        Log.d(LOG_TAG, "onStart");
}

@Override
protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "onPause");
}

@Override
protected void onRestart() {
        super.onRestart();
        Log.d(LOG_TAG, "onRestart");
}

@Override
protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume");
}

@Override
protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG, "onStop");
}

@Override
protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy");
}

SecondActivity

Los siguientes fragmentos de código muestran el código agregado en SecondActivity, pero no toda la clase.

En la parte superior de la clase SecondActivity, haz lo siguiente:

private static final String LOG_TAG = SecondActivity.class.getSimpleName();

El método returnReply():

public void returnReply(View view) {
        String reply = mReply.getText().toString();
        Intent replyIntent = new Intent();
        replyIntent.putExtra(EXTRA_REPLY, reply);
        setResult(RESULT_OK, replyIntent);
        Log.d(LOG_TAG, "End SecondActivity");
        finish();
}

Los otros métodos del ciclo de vida:

Igual que en MainActivity, arriba.

4. Tarea 2: Guarda y restablece el estado de la instancia de Activity

Según los recursos del sistema y el comportamiento del usuario, cada elemento Activity de tu app puede destruirse y reconstruirse con mucha más frecuencia de la que crees.

Es posible que hayas notado este comportamiento en la última sección cuando rotaste el dispositivo o el emulador. La rotación del dispositivo es un ejemplo de un cambio de configuración. Aunque la rotación es la más común, todos los cambios de configuración hacen que la Activity actual se destruya y se vuelva a crear como si fuera nueva. Si no tienes en cuenta este comportamiento en tu código, cuando se produzca un cambio en la configuración, es posible que el diseño de Activity vuelva a su aspecto predeterminado y valores iniciales, y que los usuarios pierdan su lugar, sus datos o el estado de su progreso en la app.

El estado de cada Activity se almacena como un conjunto de pares clave-valor en un objeto Bundle llamado estado de instancia de Activity. El sistema guarda la información de estado predeterminada en el estado de la instancia Bundle justo antes de que se detenga la Activity y pasa ese Bundle a la nueva instancia de Activity para restablecerla.

Para evitar perder datos en una Activity cuando se destruye y se vuelve a crear de forma inesperada, debes implementar el método onSaveInstanceState(). El sistema llama a este método en tu Activity (entre onPause() y onStop()) cuando existe la posibilidad de que la Activity se destruya y se vuelva a crear.

Los datos que guardas en el estado de la instancia son específicos solo de esta instancia de esta Activity específica durante la sesión actual de la app. Cuando detienes y reinicias una nueva sesión de la app, se pierde el estado de la instancia de Activity y la Activity vuelve a su aspecto predeterminado. Si necesitas guardar datos del usuario entre sesiones de la app, usa preferencias compartidas o una base de datos. Aprenderás sobre ambos en una práctica posterior.

2.1 Guarda el estado de la instancia de Activity con onSaveInstanceState()

Es posible que hayas notado que rotar el dispositivo no afecta el estado de la segunda Activity. Esto se debe a que el segundo diseño y estado de Activity se generan a partir del diseño y del Intent que la activó. Incluso si se vuelve a crear Activity, Intent sigue allí, y los datos de ese Intent se usarán cada vez que se llame al método onCreate() en la segunda Activity.

Además, quizás notes que, en cada Activity, se conserve el texto que escribiste en los elementos EditText de los mensajes o las respuestas, incluso cuando se rota el dispositivo. Esto se debe a que la información de estado de algunos de los elementos View de tu diseño se guarda automáticamente en todos los cambios de configuración, y el valor actual de EditText es uno de esos casos.

Por lo tanto, el único estado de Activity que te interesa son los elementos TextView para el encabezado de respuesta y el texto de respuesta de la Activity principal. Ambos elementos TextView son invisibles de forma predeterminada. Solo aparecen una vez que envías un mensaje a la Activity principal desde la segunda Activity.

En esta tarea, agregarás código para conservar el estado de la instancia de estos dos elementos TextView con onSaveInstanceState().

  1. Abre MainActivity.
  2. Agrega la implementación de esqueleto de onSaveInstanceState() a Activity, o usa Code > Override Methods para insertar una anulación de esqueleto.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Verifica si el encabezado es visible y, de ser así, coloca ese estado de visibilidad en el estado Bundle con el método putBoolean() y la clave "reply_visible".
    if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Recuerda que el encabezado y el texto de la respuesta se marcarán como invisibles hasta que haya una respuesta de la segunda Activity. Si el encabezado está visible, significa que hay datos de respuesta que deben guardarse. Ten en cuenta que solo nos interesa ese estado de visibilidad; no es necesario guardar el texto real del encabezado, ya que ese texto nunca cambia.

  1. Dentro de esa misma verificación, agrega el texto de respuesta a Bundle.
outState.putString("reply_text",mReplyTextView.getText().toString());

Si el encabezado es visible, puedes suponer que también lo es el mensaje de respuesta. No es necesario probar ni guardar el estado de visibilidad actual del mensaje de respuesta. Solo el texto real del mensaje pasa al estado Bundle con la clave "reply_text".

Solo guardas el estado de esos elementos View que pueden cambiar después de crear Activity. Los otros elementos View de tu app (EditText y Button) se pueden recrear desde el diseño predeterminado en cualquier momento.

Ten en cuenta que el sistema guardará el estado de algunos elementos View, como el contenido de EditText.

2.2 Restablece el estado de la instancia de Activity en onCreate()

Una vez que hayas guardado el estado de la instancia Activity, también deberás restablecerlo cuando se vuelva a crear la Activity. Puedes hacerlo en onCreate() o mediante la implementación de la devolución de llamada onRestoreInstanceState(), que se llama después de onStart() una vez creada la Activity.

La mayoría de las veces, el mejor lugar para restablecer el estado de Activity es en onCreate() para garantizar que la IU, incluido el estado, esté disponible lo antes posible. A veces, es conveniente hacerlo en onRestoreInstanceState() después de completar toda la inicialización o permitir que las subclases decidan si deseas usar tu implementación predeterminada.

  1. En el método onCreate(), después de que las variables View se inicialicen con findViewById(), agrega una prueba para asegurarte de que savedInstanceState no sea nulo.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);

// Restore the state.
if (savedInstanceState != null) {
}

Cuando se crea tu Activity, el sistema pasa el estado Bundle a onCreate() como único argumento. La primera vez que se llama a onCreate() y se inicia la app, el Bundle es null; no hay estado existente la primera vez que se inicia tu app. Las llamadas posteriores a onCreate() tendrán un paquete propagado con los datos que almacenaste en onSaveInstanceState().

  1. Dentro de esa verificación, obtén la visibilidad actual (verdadero o falso) de Bundle con la clave "reply_visible".
if (savedInstanceState != null) {
    boolean isVisible =
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Agrega una prueba debajo de la línea anterior para la variable isVisible.
if (isVisible) {
}

Si hay una clave reply_visible en el estado Bundle (y, por lo tanto, isVisible es true), deberás restablecer el estado.

  1. Dentro de la prueba isVisible, haz que el encabezado sea visible.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Obtén el mensaje de respuesta de texto de Bundle con la clave "reply_text" y configura la respuesta TextView para mostrar esa cadena.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Haz que la respuesta TextView también sea visible:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Ejecuta la app. Prueba girar el dispositivo o el emulador para asegurarte de que el mensaje de respuesta (si hay uno) permanezca en la pantalla después de volver a crear el Activity.

Código de solución de la tarea 2

En los siguientes fragmentos de código, se muestra el código de la solución para esta tarea.

MainActivity

Los siguientes fragmentos de código muestran el código agregado en MainActivity, pero no toda la clase.

El método onSaveInstanceState().

@Override
public void onSaveInstanceState(Bundle outState) {
   super.onSaveInstanceState(outState);
   // If the heading is visible, message needs to be saved.
   // Otherwise we're still using default layout.
   if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
       outState.putBoolean("reply_visible", true);
       outState.putString("reply_text",
                      mReplyTextView.getText().toString());
   }
}

El método onCreate().

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

   Log.d(LOG_TAG, "-------");
   Log.d(LOG_TAG, "onCreate");

   // Initialize all the view variables.
   mMessageEditText = findViewById(R.id.editText_main);
   mReplyHeadTextView = findViewById(R.id.text_header_reply);
   mReplyTextView = findViewById(R.id.text_message_reply);

   // Restore the saved state.
   // See onSaveInstanceState() for what gets saved.
   if (savedInstanceState != null) {
       boolean isVisible =
                     savedInstanceState.getBoolean("reply_visible");
       // Show both the header and the message views. If isVisible is
       // false or missing from the bundle, use the default layout.
       if (isVisible) {
           mReplyHeadTextView.setVisibility(View.VISIBLE);
           mReplyTextView.setText(savedInstanceState
                                  .getString("reply_text"));
           mReplyTextView.setVisibility(View.VISIBLE);
       }
   }
}

El proyecto completo:

Proyecto de Android Studio: TwoActivitiesLifecycle

5. Desafío de programación

Desafío: Crea una app de lista de compras simple con una actividad principal para la lista que está creando el usuario y otra para una lista de artículos de compras comunes.

  • La actividad principal debe contener la lista que se compilará, que debe contener diez elementos TextView vacíos.
  • Un botón de agregar artículo en la actividad principal inicia una segunda actividad que contiene una lista de artículos de compras comunes (Queso, Arroz, Manzanas, etcétera). Usa elementos Button para mostrar los artículos.
  • Cuando se elige un artículo, el usuario vuelve a la actividad principal y se actualiza una TextView vacía para incluir el artículo elegido.

Usa un Intent para pasar información de una Activity a otra. Asegúrate de que se guarde el estado actual de la lista de compras cuando el usuario rote el dispositivo.

6. Resumen

  • El ciclo de vida de la actividad es un conjunto de estados por los que migra una Activity, que comienza cuando se crea por primera vez y finaliza cuando el sistema Android recupera los recursos para esa Activity.
  • A medida que el usuario navega de una Activity a otra, dentro y fuera de tu app, cada Activity se mueve entre los estados del ciclo de vida de Activity.
  • Cada estado del ciclo de vida de la Activity tiene un método de devolución de llamada correspondiente que puedes anular en tu clase Activity.
  • Los métodos de ciclo de vida son onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop() y onDestroy().
  • Anular un método de devolución de llamada de ciclo de vida te permite agregar un comportamiento que ocurre cuando tu Activity pasa a ese estado.
  • Puedes agregar métodos de anulación de esqueleto a tus clases en Android Studio con Code > Override.
  • Los cambios en la configuración del dispositivo, como la rotación, hacen que se destruya el Activity y se vuelva a crear como si fuera nuevo.
  • Una parte del estado Activity se conserva cuando se produce un cambio de configuración, incluidos los valores actuales de los elementos EditText. Para todos los demás datos, debes guardarlos de forma explícita.
  • Guarda el estado de la instancia Activity en el método onSaveInstanceState().
  • Los datos de estado de la instancia se almacenan como pares clave-valor simples en un Bundle. Usa los métodos Bundle para ingresar datos y recuperar datos de Bundle.
  • Restablece el estado de la instancia en onCreate(), que es la forma preferida, o onRestoreInstanceState().

7. Concepto relacionado

La documentación de conceptos relacionados está en 2.2: Estado y ciclo de vida de la actividad.

8. Más información

Documentación de Android Studio:

Documentación para desarrolladores de Android:

9. Tarea

En esta sección, se enumeran las posibles actividades para el hogar para los alumnos que trabajan en este codelab como parte de un curso dirigido por un instructor. Depende del instructor hacer lo siguiente:

  • Si es necesario, asigna una tarea.
  • Comunicarles a los alumnos cómo enviar las actividades para el hogar.
  • Califica las actividades para el hogar.

Los instructores pueden usar estas sugerencias en la medida que quieran y deben asignar cualquier otra actividad para el hogar que consideren apropiada.

Si estás trabajando en este codelab por tu cuenta, usa estas actividades para el hogar para probar tus conocimientos.

Compila y ejecuta una app

  1. Crea una app con un diseño que contenga un contador TextView, un Button para aumentar el contador y un EditText. Observa la siguiente captura de pantalla como ejemplo. No es necesario que dupliques el diseño con exactitud.
  2. Agrega un controlador de clics para el Button que incrementa el contador.
  3. Ejecuta la app y aumenta el contador. Ingresa texto en EditText.
  4. Rota el dispositivo. Ten en cuenta que se restablece el contador, pero EditText no.
  5. Implementa onSaveInstanceState() para guardar el estado actual de la app.
  6. Actualiza onCreate() para restablecer el estado de la app.
  7. Asegúrate de que, cuando rotes el dispositivo, se conserve el estado de la app.

ebaf84570af6dd46.png

Responde estas preguntas:

Pregunta 1

Si ejecutas la app de la actividad para el hogar antes de implementar onSaveInstanceState(), ¿qué sucede si rotas el dispositivo? Elige una opción:

  • El elemento EditText ya no contiene el texto que ingresaste, pero el contador se conserva.
  • El contador se restablece a 0, y el elemento EditText ya no contiene el texto que ingresaste.
  • El contador se restablece a 0, pero el contenido de EditText se conserva.
  • El contador y el contenido de EditText se conservan.

Pregunta 2

¿A qué métodos de ciclo de vida de Activity se los llama cuando ocurre un cambio en la configuración del dispositivo (como la rotación)? Elige una opción:

  • Android cierra inmediatamente tu Activity llamando a onStop(). Tu código debe reiniciar Activity.
  • Para cerrar tu Activity, Android llama a onPause(), onStop() y onDestroy(). Tu código debe reiniciar Activity.
  • Para cerrar tu Activity, Android llama a onPause(), onStop() y onDestroy(), y vuelve a iniciarlo. Para hacerlo, llama a onCreate(), onStart() y onResume().
  • Android llama inmediatamente a onResume().

Pregunta 3

¿En qué momento del ciclo de vida de Activity se llama a onSaveInstanceState()? Elige una opción:

  • Se llama a onSaveInstanceState() antes del método onStop().
  • Se llama a onSaveInstanceState() antes del método onResume().
  • Se llama a onSaveInstanceState() antes del método onCreate().
  • Se llama a onSaveInstanceState() antes del método onDestroy().

Pregunta 4

¿Qué métodos del ciclo de vida de Activity son los más útiles para guardar datos antes de que finalice o destruya Activity? Elige una opción:

  • onPause() o onStop()
  • onResume() o onCreate()
  • onDestroy()
  • onStart() o onRestart()

Cómo enviar tu app para que se la califique

Orientación para calificadores

Verifica que la app tenga las siguientes funciones:

  • Muestra un contador, un Button para aumentarlo y un elemento EditText.
  • Si haces clic en Button, el contador aumentará en 1.
  • Cuando se rota el dispositivo, se conservan los estados del contador y de EditText.
  • La implementación de MainActivity.java usa el método onSaveInstanceState() para almacenar el valor del contador.
  • La implementación de onCreate() comprueba la existencia de outState Bundle. Si ese Bundle existe, se restablece el valor del contador y se guarda en TextView.

10. Próximo codelab

Para encontrar el siguiente codelab práctico del curso Conceptos básicos para desarrolladores de Android (V2), consulta Codelabs de Conceptos básicos para desarrolladores de Android (V2).

Para obtener una descripción general del curso, incluidos los vínculos a los capítulos conceptuales, las apps y las diapositivas, consulta Conceptos básicos para desarrolladores de Android (versión 2).