Skip to content

Most visited

Recently visited

navigation

Tareas y pila de actividades

Una aplicación generalmente contiene múltiples actividades. Cada actividad debe diseñarse en torno a una clase específica de acción que el usuario puede realizar y puede iniciar otras actividades. Por ejemplo, una aplicación de correo electrónico puede tener una actividad para mostrar una lista de mensajes nuevos. Cuando el usuario selecciona un mensaje, se abre una actividad nueva para ver ese mensaje.

Una actividad puede incluso iniciar actividades que existen en otras aplicaciones del dispositivo. Por ejemplo, si tu aplicación desea enviar un mensaje de correo electrónico, puedes definir una intent para realizar una acción de "enviar" e incluir algunos datos, como una dirección de correo electrónico y un mensaje. Luego, se abre una actividad de otra aplicación que se declara a sí misma para manejar esta clase de intent. En este caso, la intent es enviar un correo electrónico, por lo tanto, se inicia una actividad de "redacción" de la aplicación de correo electrónico (si múltiples actividades admiten la misma intent, el sistema permite que el usuario seleccione la que desea utilizar). Cuando se envía el correo electrónico, tu actividad se reanuda y parece que la actividad de correo electrónico fuera parte de tu aplicación. Si bien las actividades pueden ser de diferentes aplicaciones, Android mantiene esta experiencia del usuario ininterrumpida al mantener ambas actividades en la misma tarea.

Una tarea es una colección de actividades con la que los usuarios interactúan cuando realizan un trabajo determinado. Las actividades se organizan en una pila (la pila de actividades), en el orden en el que se abre cada actividad.

La pantalla principal del dispositivo es el lugar donde se inician la mayoría de las tareas. Cuando el usuario toca un ícono en el lanzador de la aplicación (o un acceso directo en la pantalla principal), la tarea de esa aplicación pasa a primer plano. Si no existe una tarea para la aplicación (la aplicación no se ha utilizado recientemente), se crea una nueva tarea y la actividad "principal" de esa aplicación se abre como la actividad raíz de la pila.

Cuando la actividad actual inicia otra actividad, la actividad nueva pasa a la parte superior de la pila y tiene foco. La actividad anterior continúa en la pila, pero está detenida. Cuando una actividad se detiene, el sistema retiene el estado actual de su interfaz de usuario. Cuando el usuario presiona el botón Atrás , se saca la actividad actual de la parte superior de la pila (se destruye la actividad) y se reanuda la actividad anterior (se restaura el estado anterior de su interfaz de usuario). Las actividades de la pila nunca se reorganizan, solo se insertan y se sacan de la pila; se insertan en la pila cuando son iniciadas por la actividad actual y se sacan cuando el usuario la abandona utilizando el botón Atrás. Por lo tanto, la pila de actividades funciona como una estructura de objetos "el último en entrar es el primero en salir". En la figura 1, se visualiza este comportamiento con una línea de tiempo que muestra el progreso entre actividades junto con la pila de actividades actual en cada momento.

Figura 1: Representación de la forma en que cada actividad nueva en una tarea agrega un elemento a la pila de retroceso. Cuando el usuario presiona el botón Atrás, se destruye la actividad actual y se reanuda la actividad anterior.

Si el usuario continúa presionando el botón Atrás, se saca cada actividad de la pila para revelar la anterior, hasta que el usuario vuelve a la pantalla principal (o a la actividad que se estaba ejecutando cuando se inició la tarea). Cuando se quitan todas las actividades de la pila, la tarea ya no existe.

Figura 2: Dos tareas: La tarea B recibe una interacción del usuario en primer plano, mientras que la tarea A está en segundo plano, esperando que se la reanude.

Figura 3: Se crean instancias de una sola actividad varias veces.

Una tarea es una unidad cohesiva que puede pasar al "segundo plano" cuando los usuarios inician una tarea nueva o van a la pantalla principal mediante el botón Inicio. Mientras están en segundo plano, todas las actividades de la tarea se detienen, pero la pila de retroceso de esta permanece intacta; la tarea simplemente pierde el foco mientras otra tiene lugar, como se muestra en la figura 2. Una tarea luego puede volver a “primer plano” para que los usuarios puedan continuar desde donde la habían abandonado. Suponga, por ejemplo, que la tarea actual (tarea A) tiene tres actividades en su pila; dos en la actividad actual. El usuario presiona el botón Inicio , y luego inicia una aplicación nueva desde el lanzador de aplicaciones. Cuando aparece la pantalla principal, la tarea A pasa a segundo plano. Cuando se inicia la aplicación nueva, el sistema inicia una tarea para esa aplicación (tarea B) con su propia pila de actividades. Después de interactuar con esa aplicación, el usuario vuelve nuevamente a la página principal y selecciona la aplicación que inició originalmente la tarea A. Ahora, la tarea A pasa a primer plano; las tres actividades de la pila están intactas y se reanuda la actividad de la parte superior de la pila. En este punto, el usuario también puede volver a la tarea B yendo a la página principal y seleccionando el ícono de la aplicación que inició esa tarea (o seleccionando la tarea de la aplicación desde la pantalla de información general). Este es un ejemplo de multitarea en Android.

Nota: Puede haber varias tareas en segundo plano a la vez. Sin embargo, si el usuario ejecuta muchas tareas en segundo plano al mismo tiempo, el sistema podría comenzar a destruir actividades en segundo plano para recuperar memoria, y hacer que se pierdan los estados de actividad. Consulta la sección siguiente, Estado de actividad.

Dado que las actividades de la pila de actividades nunca se reorganizan, si tu aplicación permite que los usuarios inicien una actividad determinada desde más de una actividad, se crea una instancia nueva de esa actividad y se la inserta en la pila (en lugar de pasar una instancia anterior de la actividad a la parte superior). Por lo tanto, quizá se creen instancias de una actividad de tu aplicación varias veces (incluso desde diferentes tareas), como se muestra en la figura 3. Por lo tanto, si el usuario navega hacia atrás usando el botón Atrás, cada instancia de la actividad se revela en el orden en que se abrieron (cada una con su propio estado de IU). Sin embargo, puedes modificar este comportamiento si no deseas que se creen instancias de una actividad más de una vez. En la sección Cómo administrar tareas, se explica cómo hacerlo.

En resumen, el comportamiento predeterminado de las actividades y las tareas es el siguiente:

Diseño de navegación

Para obtener más información sobre cómo funciona la navegación de las aplicaciones en Android, lee la guía de Navegación de Diseño Android.

Cómo guardar el estado de una actividad

Como se explicó anteriormente, el comportamiento predeterminado del sistema preserva el estado de una actividad cuando esta se detiene. De este modo, cuando los usuarios vuelven a una actividad anterior, su interfaz de usuario aparece como la habían dejado. Sin embargo, tú puedes (y debes) retener de manera proactiva el estado de tus actividades utilizando métodos de callback, en caso de que la actividad se destruya y sea necesario volver a crearla.

Cuando el sistema detiene una de tus actividades (por ejemplo, cuando se inicia una actividad nueva o la tarea pasa a segundo plano), es posible que el sistema destruya esa actividad completamente si necesita recuperar memoria del sistema. Cuando esto sucede, se pierde la información sobre el estado de la actividad. Si esto sucede, el sistema aún sabe que la actividad tiene un lugar en la pila de actividades, pero cuando se lleva la actividad a la parte superior de la pila, el sistema debe volver a crearla (en lugar de reanudarla). Para evitar que se pierda el trabajo del usuario, debes retenerlo proactivamente implementando los métodos de callback onSaveInstanceState() en tu actividad.

Para obtener más información sobre cómo guardar el estado de actividad, consulta el documento Actividades .

Cómo administrar tareas

La forma en la que Android administra las tareas y la pila de actividades, como se describió anteriormente (colocando todas las actividades iniciadas en sucesión en la misma tarea y en una pila “el último en entrar es el primero en salir”) funciona perfectamente para la mayoría de las aplicaciones, y no es necesario que te preocupes sobre cómo tus actividades se asocian con las tareas o de cómo existen en la pila de actividades. Sin embargo, puedes decidir que deseas interrumpir el comportamiento normal. Quizá desees que una actividad de tu aplicación comience una tarea nueva cuando se la inicia (en lugar de colocarla dentro de la tarea actual); o bien, cuando inicias una actividad, deseas poner en primer plano una instancia existente de dicha actividad (en lugar de crear una instancia nueva en la parte superior de la pila de actividades); o bien, deseas que se eliminen todas las actividades de su pila de actividades , excepto la actividad raíz, cuando el usuario deja la tarea.

Puedes hacer todo esto y más, con atributos en el elemento de manifiesto <activity> y con indicadores en la intent que pasa a startActivity().

En este sentido, los principales atributos <activity> que puedes usar son los siguientes:

Y los principales indicadores de intent que puedes utilizar son los siguientes:

En las secciones siguientes, verás cómo puedes utilizar los atributos del manifiesto y los indicadores de intent para definir cómo se asocian las actividades con las tareas y cómo se comportan en la pila de actividades.

Además, por separado, se explica cómo las tareas y las actividades pueden representarse y administrarse en la pantalla de información general. Consulta Pantalla de información general para obtener más información. Normalmente, debes permitir que el sistema defina cómo se representan tus tareas y actividades en la pantalla de información general, y no es necesario que modifiques este comportamiento.

Advertencia: La mayoría de las aplicaciones no deben interrumpir el comportamiento predeterminado de las actividades y tareas. Si determinas que es necesario que tu actividad modifique los comportamientos predeterminados, ten precaución y asegúrate de comprobar la usabilidad de la actividad durante el lanzamiento y cuando se vuelve a ella desde otras actividades y tareas con el botón Atrás. Asegúrate de comprobar los comportamientos de navegación que podrían entrar en conflicto con el comportamiento previsto del usuario.

Cómo definir modos de lanzamiento

Los modos de lanzamiento te permiten definir cómo se asocia una instancia nueva de una actividad con la tarea actual. Puedes definir diferentes modos de lanzamiento de dos formas:

Por lo tanto, si la actividad A inicia la actividad B, la actividad B puede definir en su manifiesto cómo se debe asociar con la tarea actual (si es que debe hacerlo) y la actividad A también puede solicitar cómo la actividad B debe asociarse con la tarea actual. Si ambas actividades definen cómo la actividad B debe asociarse con una tarea, se respeta la solicitud de la actividad A (definida en la intent) en lugar de la solicitud de la actividad B (definida en su manifiesto).

Nota: Algunos modos de lanzamiento disponibles para el archivo de manifiesto no están disponibles como indicadores para una intent y, del mismo modo, algunos modos de lanzamiento disponibles como indicadores para una intent no pueden definirse en el manifiesto.

Mediante el archivo de manifiesto

Cuando declares una actividad en tu archivo de manifiesto, puedes especificar la manera de asociar la actividad con una tarea mediante el atributo launchMode del elemento<activity>.

El atributo launchMode especifica una instrucción sobre cómo se debe lanzar la actividad en una tarea. Existen cuatro modos de lanzamiento diferentes que puedes asignar al atributo launchMode:

"standard" (modo predeterminado)
Predeterminado. El sistema crea una instancia nueva de la actividad en la tarea desde la cual se inició y dirige la intent hacia dicha tarea. Se pueden crear instancias de la actividad varias veces, cada instancia puede pertenecer a diferentes tareas, y una tarea puede tener varias instancias.
"singleTop"
Si una instancia de la actividad ya existe al comienzo de la tarea de destino, el sistema direcciona la intent hacia dicha instancia mediante una llamada a su método onNewIntent() en lugar de crear una nueva instancia de la actividad. Se pueden crear instancias de la actividad varias veces, cada instancia puede pertenecer a diferentes tareas, y una tarea puede tener varias instancias (pero solo si la actividad de la parte superior de la pila de actividades no es una instancia existente de la actividad).

Por ejemplo, supón que la pila de actividades de una tarea está formada por la actividad raíz A con actividades B, C y D en la parte superior (la pila es A-B-C-D; D está en la parte superior). Se recibe una intent para una actividad de tipo D. Si D tiene el modo de lanzamiento "standard" predeterminado, se lanza una instancia nueva de la clase y la pila pasa a ser A-B-C-D-D. Sin embargo, si el modo de lanzamiento de D es "singleTop", la instancia existente de D recibe la intent a través de onNewIntent(), porque está en la parte superior de la pila; la pila sigue siendo A-B-C-D. Sin embargo, si llega una intent para una actividad de tipo B, se agrega una instancia nueva de B a la pila, aun cuando el modo de lanzamiento es "singleTop".

Nota: Cuando se crea una instancia nueva de una actividad, el usuario puede presionar el botón Atrás para volver a la actividad anterior. Sin embargo, cuando una instancia existente de una actividad maneja la intent nueva, el usuario no puede presionar el botón Atrás para volver al estado de la actividad antes de que la nueva intent llegue a onNewIntent().

"singleTask"
El sistema crea una tarea nueva y crea instancias de la actividad en la raíz de la tarea nueva. Sin embargo, si una instancia de la actividad ya existe en una tarea independiente, el sistema dirige la intent a la instancia existente a través de una llamada a su método onNewIntent(), en lugar de crear una instancia nueva. Solo una instancia de la actividad puede existir a la vez.

Nota: Si bien la actividad se inicia en una tarea nueva, el botón Atrás sigue llevando al usuario a la actividad anterior.

"singleInstance".
Es igual que "singleTask", con la excepción de que el sistema no lanza otras actividades en la tarea que contiene la instancia. La actividad es siempre el único miembro de su tarea; todas las actividades iniciadas por esta actividad se abren en una tarea independiente.

En otro ejemplo, la aplicación del navegador de Android declara que la actividad del navegador web debe abrirse siempre en su propia tarea; al especificar el modo de lanzamiento singleTask en el elemento <activity>. Esto significa que si tu aplicación emite una intent para abrir el navegador de Android, tu actividad no está ubicada en la misma tarea que tu aplicación. En cambio, se inicia una tarea nueva para el navegador o, si el navegador ya tiene una tarea ejecutándose en segundo plano, esa tarea se lleva a primer plano para que maneje la intent nueva.

Independientemente de que una actividad se inicie en una tarea nueva o en la misma tarea que la actividad que la inició, el botón Atrás siempre lleva al usuario a la actividad anterior. Sin embargo, si inicias una actividad que especifica el modo de lanzamiento singleTask, y si una instancia de esa actividad existe en una tarea en segundo plano, esa tarea completa pasa a primer plano. En este punto, la pila de actividades ahora incluye todas las actividades de la tarea que pasó a primer plano, en la parte superior de la pila. En la figura 4 se ilustra este tipo de escenario.

Figura 4: Una representación de la manera en que una actividad con el modo de lanzamiento “singleTask” se agrega a la pila de retroceso. Si la actividad ya forma parte de una tarea en segundo plano con su propia pila de actividades, toda la pila de actividades también pasa a primer plano, en la parte superior de la tarea actual.

Para obtener más información sobre el uso de modos de lanzamiento en el archivo de manifiesto, consulta la documentación del elemento <activity> , donde se explican en más detalle el atributo launchMode y los valores aceptados.

Nota: Los comportamientos que especificas para tu actividad con el atributo launchMode pueden reemplazarse por indicadores incluidos con la intent que inicie tu actividad, como se explica en la sección siguiente.

Mediante los indicadores de intent

Cuando inicias una actividad, puedes modificar la asociación predeterminada de una actividad con su tarea incluyendo indicadores en la intent que entregas a startActivity(). Los indicadores que puedes utilizar para modificar el comportamiento predeterminado son los siguientes:

FLAG_ACTIVITY_NEW_TASK
Inicia la actividad en una tarea nueva. Si ya se está ejecutando una tarea para la actividad que inicia ahora, esa tarea pasa a primer plano con su último estado restaurado y la actividad recibe la intent nueva en onNewIntent().

Esto produce el mismo comportamiento que el valor "singleTask" launchMode, explicado en la sección anterior.

FLAG_ACTIVITY_SINGLE_TOP
Si la actividad que se inicia es la actividad actual (en la parte superior de la pila de actividades), la instancia existente recibe una llamada a onNewIntent(), en lugar de crear una instancia nueva de la actividad.

Esto produce el mismo comportamiento que el valor "singleTop" launchMode, explicado en la sección anterior.

FLAG_ACTIVITY_CLEAR_TOP
Si la actividad que se inicia ya se está ejecutando en la tarea actual, en lugar de lanzar una instancia nueva de esa actividad, todas las demás actividades de la parte superior de esta se destruyen y esta intent se entrega a la instancia reanudada de la actividad (ahora en la parte superior), a través de onNewIntent()).

No existe un valor para el atributo launchMode que produce este comportamiento.

FLAG_ACTIVITY_CLEAR_TOP se usa generalmente en junto con FLAG_ACTIVITY_NEW_TASK. Cuando se usan juntos, estos indicadores representan un método para ubicar una actividad existente en otra tarea y disponerla en una posición en la cual pueda responder a la intent.

Nota: Si el modo de lanzamiento de la actividad designada es "standard", este también se elimina de la pila y se lanza una instancia nueva en su lugar para manejar la intent entrante. Esto se debe a que siempre se crea una instancia nueva para una intent nueva cuando el modo de lanzamiento es "standard".

Cómo manejar afinidades

La afinidad indica a qué tarea prefiere pertenecer una actividad. De forma predeterminada, todas las actividades de la misma aplicación tienen afinidad mutuamente. Por lo tanto, de forma predeterminada, todas las actividades de la misma aplicación prefieren estar en la misma tarea. Sin embargo, puedes modificar la afinidad predeterminada para una actividad. Las actividades definidas en diferentes aplicaciones pueden compartir una afinidad, o bien, se pueden asignar distintas afinidades de tareas a las actividades definidas en la misma aplicación.

Puedes modificar la afinidad de cualquier actividad con el atributo taskAffinity del elemento <activity>.

El atributo taskAffinity toma un valor de string, que debe ser exclusivo del nombre del paquete predeterminado declarado en el elemento <manifest>, ya que el sistema usa ese nombre para identificar la afinidad de tarea predeterminada de la aplicación.

La afinidad entra en juego en dos circunstancias:

Sugerencia: Si un archivo .apk contiene más de una “aplicación” desde el punto de vista del usuario, probablemente te convenga usar el atributo taskAffinity para asignar diferentes afinidades a las actividades asociadas con cada “aplicación”.

Cómo borrar la pila de actividades

Si el usuario deja una tarea por mucho tiempo, el sistema borra todas las actividades de la tarea excepto la actividad raíz. Cuando el usuario vuelve nuevamente a la tarea, solo se restaura la actividad raíz. El sistema se comporta de esta forma porque, después de un período prolongado, es probable que los usuarios hayan abandonado lo que estaban haciendo anteriormente y hayan vuelto a la tarea para comenzar algo nuevo.

Existen algunos atributos de actividades que puedes utilizar para modificar este comportamiento:

alwaysRetainTaskState
Si este atributo se fija en "true" en la actividad raíz de una tarea, el comportamiento predeterminado recién descrito no tiene lugar. La tarea retiene todas las actividades en su pila incluso después de un período prolongado.
clearTaskOnLaunch
Si este atributo se fija en "true" en la actividad raíz de una tarea, la pila se borra hasta la actividad raíz cada vez que el usuario abandona la tarea y vuelve a ella. En otras palabras, es lo opuesto de alwaysRetainTaskState. El usuario siempre vuelve a la tarea en su estado inicial, incluso después de dejar la tarea solo por un momento.
finishOnTaskLaunch
Este atributo es como clearTaskOnLaunch, pero funciona en una sola actividad, no en una tarea completa. También puede hacer que se elimine una actividad , incluida la actividad raíz. Cuando se fija en "true", la actividad sigue siendo parte de la tarea solo durante la sesión actual. Si el usuario deja la tarea y luego vuelve a ella, la actividad ya no está presente.

Cómo iniciar una tarea

Puedes configurar una actividad como punto de entrada de una tarea proporcionándole un filtro de intent con "android.intent.action.MAIN" como acción especificada y "android.intent.category.LAUNCHER" como categoría especificada. Por ejemplo:

<activity ... >
    <intent-filter ... >
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    ...
</activity>

Un filtro de intent de esta clase hace que se muestren un ícono y una etiqueta de la actividad en el lanzador de la aplicación, lo que brinda a los usuarios una forma de lanzar la actividad y volver a la tarea que esta crea en cualquier momento después de haber sido lanzada.

Esta segunda capacidad es importante: los usuarios deben ser capaces de dejar una tarea y volver a ella más adelante utilizando este lanzador de actividades. Por este motivo, los dos métodos de lanzamiento que marcan que las actividades siempre inician una tarea, "singleTask" y "singleInstance", deben usarse solo cuando la actividad tenga un filtro ACTION_MAIN y CATEGORY_LAUNCHER. Imagina, por ejemplo, qué podría ocurrir si el filtro no está presente: Una intent lanza una actividad "singleTask", con lo cual se inicia una tarea nueva, y el usuario trabaja en esa tarea durante un tiempo. El usuario luego presiona el botón Inicio . La tarea se envía a segundo plano y no es visible. Ahora el usuario no tiene forma de volver a la tarea, porque esta no está representada en el lanzador de la aplicación.

En casos en los cuales no desees que el usuario pueda volver a la actividad, fija el finishOnTaskLaunch del elemento <activity> en "true" (consulta la sección Cómo borrar la pila).

La forma en la que las tareas y las actividades se representan y se administran en la pantalla de información general se explica en más detalle en la sección Pantalla de información general.

This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.