viernes, 12 de septiembre de 2014

Fragmentos

Una fragmento es un objeto de tipo Fragment que aporta su propia lógica y aspecto (IU) a una actividad. Una actividad puede contener más de un fragmento y éstos podrán ser reutilizados en varias actividades. Podemos pensar en los fragmentos como en los módulos de una actividad que cuentan con su propio ciclo de vida y que pueden ser añadidos y eliminados de una actividad mientras ésta se esté ejecutando.

Un fragmento siempre estará contenido en una actividad y su ciclo de vida dependerá del ciclo de vida de ésta. Por ejemplo, cuando una actividad entra en pausa, todos sus fragmentos también entrarán en pausa, y cuando una actividad es destruida, todos sus fragmentos también serán destruidos. Sin embargo, mientras una actividad se está ejecutando (es decir, se encuentra en estado reanudada), el estado de cada fragmento funcionará de manera independiente. Además, podremos añadir, eliminar o reemplazar fragmentos a nuestro antojo a través de un mecanismo basado en transacciones. Cada transacción, antes de ser confirmada, podrá ser registrada en una pila de retroceso para fragmentos que gestiona la propia actividad y que permitirá al usuario volver a estados previos con tan solo pulsar el botón de retroceso.

Como norma general, cuando añadimos un fragmento a una actividad, lo que estamos haciendo es insertando su plantilla dentro de la plantilla de la actividad. Podemos insertar un fragmento en una actividad de dos formas: de manera estática, añadiendo un elemento <fragment> a la plantilla de la actividad, o de manera dinámica, añadiendo el fragmento desde el código a una vista contenedora (ViewGroup) previamente instanciada. Sin embargo, no todos los fragmentos cuentan con una plantilla y su objetivo principal consistirá en aportar funcionalidad adicional a una actividad.

Filosofía de diseño.

Android introdujo los fragmentos a partir de la versión 3.0 (versión 11 de la API) principalmente para flexibilizar el proceso de elaboración de interfaces de usuario en dispositivos con pantallas de mayor tamaño. Debido a que la pantalla de una tableta suele ser mucho más grande que la pantalla de un teléfono inteligente, dispondremos de más espacio para combinar e intercambiar elementos de la interfaz. Los fragmentos nos permiten este tipo de diseños sin que tengamos que realizar operaciones complejas dentro de la estructura jerárquica de vistas de una plantilla. Dividir la plantilla de una actividad en fragmentos, nos permitirá transformar la apariencia de nuestra actividad en tiempo de ejecución y nos permitirá registrar los cambios en una pila de retroceso para fragmentos desde la que podremos recuperar estados previos.

Por ejemplo, una aplicación de noticias puede usar un fragmento para mostrar una lista de artículos en la parte izquierda de la pantalla y otro fragmento para mostrar los detalles del artículo previamente seleccionado en su parte derecha.  En vez de utilizar una actividad para seleccionar un artículo de una lista y mostrar el artículo seleccionado en otra actividad, el usuario podrá seleccionar un artículo y leerlo dentro de la misma actividad (ver imagen 1). Ambos fragmentos pertenecen a la misma actividad, gestionan sus propios ciclos de vida y reaccionarán por separado en respuesta a las interacciones con el usuario.

Deberíamos ser capaces de diseñar nuestros fragmentos como módulos que van a ser usados por varias actividades. Podemos hacerlo así porque cada fragmento cuentan con su propia plantilla, comportamiento y ciclo de vida. Debemos evitar las dependencias entre fragmentos. Un diseño modular nos permitirá hacer varias combinaciones de nuestros fragmentos en función del tamaño de pantalla. Cuando diseñamos una aplicación para funcionar tanto en tabletas como en teléfonos inteligentes, podremos combinar los fragmentos de la manera más óptima en función de sus tamaños de pantalla.

Diseño modular de fragmentos para tabletas y móviles
Imagen 1. Diseño modular de dos fragmentos para ser mostrados tanto en tabletas como en móviles.
Continuando con el ejemplo de la aplicación de noticias, ésta podría combinar dos fragmentos en una actividad A cuando se ejecuta en una tableta. Sin embargo, cuando se ejecuta en un teléfono inteligente, no habrá suficiente espacio para mostrar ambos fragmentos. En este caso, la actividad A mostraría solo un listado con los artículos a la espera de que el usuario seleccionase uno. Una vez el usuario selecciona un artículo, iniciaríamos una actividad B con el segundo fragmento para mostrar los detalles del artículo seleccionado.

Creando un fragmento.

Ciclo de vida de un fragmento
Imagen 2. Ciclo de vida de un fragmento.
Un fragmento se crea extendiendo la clase Fragment (o una clase descendiente). Los fragmentos distribuyen su código de manera parecida a como lo hacen las actividades. Cuentan con los mismos métodos retrollamada de una actividad: onCreate(), onStart(), onPause() y onStop(). De hecho, si tuviésemos que usar fragmentos en una aplicación ya existente, deberíamos ser capaces de hacerlo de una manera sencilla con tan solo mover el código desde las retrollamadas de nuestra actividad hasta, sus respectivas retrollamadas en nuestro fragmento.

Generalmente, deberíamos implementar al menos los siguientes métodos:
onCreate()
Este método es invocado por el sistema cuando crea el fragmento. Dentro deberíamos inicializar componentes esenciales que queremos perduren a lo largo de su ciclo de vida.
onCreataView()
Este método es invocado por el sistema cuando el fragmento pinta su interfaz de usuario por primera vez. Este método devuelve un objeto de tipo View con la plantilla del fragmento ya instanciada. Si el fragmento no tiene plantilla, devolvemos null.
onPause()
El sistema llama a este método cada vez que el usuario abandona el fragmento (esto no significa que el fragmento acabe siendo destruido). Es el sitio adecuado para guardar datos persistentes (recuerda que el usuario no tiene por qué volver).

La mayoría de las aplicaciones deberían implementar al menos estos tres métodos para cualquier fragmento, pero hay otros métodos que también podríamos utilizar para gestionar otras etapas del ciclo de vida.

Existen otro tipo de fragmentos en los que podríamos estar interesados:
DialogFragment
Que muestra un cuadro de diálogo. Usar esta clase para crear un cuadro de diálogo es una buena alternativa a los métodos disponibles en la clase Activity.  Ten en cuenta que un fragmento de tipo DialogFragment podrás añadirlo a la pila de retroceso para fragmentos, permitiendo al usuario volver a recuperar un fragmento previamente eliminado.
ListFragment
Muestra un listado de elementos asociados a un adaptador (como SimpleCursorAdapter). Parecido a lo que hace una actividad ListActivity. Nos proporciona métodos retrollamada adicionales asociados a los elementos de la lista (onListItemClick(), por ejemplo).
PreferenceFragment
Muestra un objeto de tipo Preference como una lista. Parecido a lo que hace una actividad PreferenceActivity. Este tipo de fragmento es útil cuando necesitemos un panel de preferencias para configurar nuestra aplicación.

Añadiendo la interfaz del usuario.

Lo habitual es que un fragmento cuente con su propia plantilla y que ésta se integre con la plantilla de la actividad. Para añadir una plantilla a un fragmento, implementaremos el método onCreateView, que será invocado por el sistema cuando éste necesite pintar el fragmento. Este método devolverá un objeto de tipo View, con la plantilla instanciada.

Nota. Si el fragmento es de tipo ListFragment, el método onCreateView devolverá por defecto un objeto de tipo ListView, por lo que no tendremos que implementarlo.

El objeto View asociado a la plantilla del fragmento, lo construiremos a partir del archivo XML asociado a la plantilla. Para ello utilizaremos el objeto LayoutInflater, que nos ayudará a transformar el código XML de nuestra plantilla en un objeto de tipo View. En el siguiente ejemplo utilizamos la plantilla res/layout/example_fragment.xml como base:
public static class ExampleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Construimos la vista a partir del recurso XML y devolvemos la vista generada
        return inflater.inflate(R.layout.example_fragment, container, false);
    }
}

El parámetro container hace referencia a la vista contenedora de la actividad en la que queremos insertar el fragmento. El parámetro savedInstanceState es el objeto de tipo Bundle que utilizaremos en el caso de que necesitemos restaurar una instancia previa del fragmento.

El método inflate() tiene tres parámetros:
  • El identificador asociado con el recurso XML, plantilla del fragmento.
  • El vista contenedora (ViewGroup) del fragmento. Importante especificar este argumento para que el sistema pueda aplicar los parámetros de la plantilla contenedora al elemento raíz de la vista resultante.
  • Un valor indicando si queremos que la vista resultante incluya o no la vista contenedora. En el ejemplo, el valor false indica que no se añada puesto que ya se ha hecho con anterioridad y hacerlo de nuevo, ocasionaría redundancias en la plantilla final.

Añadiendo un fragmento a una actividad.

Generalmente, los fragmentos contribuyen aportando su propia IU como parte de la IU de la actividad que los contiene. Hay dos formas de añadir un fragmento a la IU de una actividad:
  • De manera estática, declarando el fragmento en la plantilla de la actividad. En el siguiente ejemplo declaramos dos fragmentos en la actividad:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <fragment android:name="com.example.news.ArticleListFragment"
                android:id="@+id/list"
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="match_parent" />
        <fragment android:name="com.example.news.ArticleReaderFragment"
                android:id="@+id/viewer"
                android:layout_weight="2"
                android:layout_width="0dp"
                android:layout_height="match_parent" />
    </LinearLayout>
    

    El atributo android:name de un elemento <fragment> hace referencia a la clase Fragment definida para cada fragmento.

    Para construir la plantilla de la actividad, el sistema crea una instancia para cada uno de los fragmentos declarados en su interior, obtiene sus vistas asociadas llamando a sus métodos onCreateView(), y por último, sustituye cada uno de los elementos <fragment> con la vista correspondiente.

    Nota. Cada fragmento necesita de un identificador que el sistema usará para restaurarlo cada vez que la actividad sea reiniciada. El identificador también nos servirá para poder obtener el fragmento desde el código y posteriormente borrarlo o reemplazarlo por otro si fuera necesario. Hay tres maneras de especificar un identificador en un fragmento:
    • A través del atributo android:id. (identificador).
    • A través del atributo android:tag. (etiqueta).
    • Si no especificamos ninguno de los dos anteriores, el sistema usar el identificador de la vista contenedora.

  • De manera dinámica, añadiendo el fragmento a una vista contenedora ViewGroup desde el propio código.

    Mientras nuestra actividad se está ejecutando, podremos añadir fragmentos en cualquier momento. Simplemente necesitamos especificar la vista contenedora ViewGroup en la que queremos añadirlo.

    Para realizar transacciones con fragmentos desde nuestra actividad (añadir, borrar o reemplazar fragmentos), tendremos que usar un objeto de tipo FragmentTransaction. Podemos obtenerlo desde la actividad de la siguiente manera:
    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    
    A partir de este momento podremos utilizar el método add(), especificando el fragmento que queremos añadir y su vista contenedora:
    ExampleFragment fragment = new ExampleFragment();
    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
    
    Para confirmar las operaciones realizadas durante la transacción, al final siempre haremos una llamada al método commit().

Añadiendo un fragmento sin IU.

En los ejemplos anteriores se muestra cómo añadir fragmentos que ya cuentan con su propia interfaz de usuario. Sin embargo, podemos usar fragmentos que solo aporten funcionalidad a nuestras actividades sin la necesidad de que éstos formen parte de la IU.

Para añadir un fragmento sin interfaz de usuario desde el código de una actividad usaremos el método add(Fragment, String), proporcionando la etiqueta (atributo android:tag) asociada al fragmento en lugar de utilizar el identificador asociado a la vista contenedora. Esto añadirá el fragmento a la actividad y al no estar asociado con una vista, no se invocará su método onCreateView(), por lo que no será necesaria su implementación.

Especificar una etiqueta en un fragmento, no es exclusivo de este tipo de fragmentos que carecen de IU, también podrás utilizarlo con fragmentos que dispongan de IU. Si utilizas una etiqueta para identificar al fragmento, ésta será la única manera de hacer referencia a él. Para obtener el fragmento desde la actividad, tendremos que usar el método findFragmentByTag().

Trabajando con fragmentos.

Para trabajar con fragmentos desde una actividad, haremos uso de la clase FragmentManager. Podemos obtener su instancia desde la propia actividad llamando al método getFragmentManager().

Las operaciones que podremos realizar con el gestor de fragmentos son:
  • Obtener fragmentos que ya existan en la actividad utilizando los métodos getFragmentById() (para fragmentos con IU) y getFragmentByTag() (para fragmentos sin IU).
  • Sacar fragmentos de la pila de retroceso para fragmentos con el método popBackStack() (simulando el botón de retroceso del usuario).
  • Controlar cambios en la pila de retroceso implementando la interfaz addOnBackStackChangedListener().

Es evidente, como ya vimos anteriormente, que también podemos utilizar el gestor de fragmentos para realizar transacciones con fragmentos (añadirlos, eliminarlos o reemplazarlos).

Realizando transacciones con fragmentos.

Una de las características más importantes de usar fragmentos en nuestras actividades es que éstos pueden ser añadidos, eliminados, reemplazados y realizar otras operaciones con ellos en respuesta a la interacción con el usuario. Por cada conjunto de cambios que realicemos seguidos de un commit(), estaremos realizando una transacción. Podemos guardar cada transacción en la pila de retroceso para fragmentos, permitiendo de esta forma que el usuario pueda recuperar transacciones previas (similar a como lo hacemos con las actividades).

Podemos realizar todos los cambios que queramos para una transacción, haciendo uso de los métodos add(), remove() y replace() del gestor de fragmentos. Para aplicar los cambios, utilizaremos el método commit().

Antes de confirmar los cambios de una transacción podemos usar el método addToBackStack() para registrar la transacción actual en la pila de retroceso. La pila es gestionada por la actividad y permitirá al usuario navegar a un estado previo pulsando el botón de retroceso. En el siguiente ejemplo veremos cómo reemplazar un fragmento por otro y cómo guardar la transacción en la pila de retroceso:
// Creamos el fragmento y empezamos la transacción
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Reemplazamos el fragmento de su vista contenedora fragment_container,
// y añadimos la transacción a la pila de retroceso
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Confirmamos la transacción
transaction.commit();
En el ejemplo, newFragment reemplaza el contenido de la vista contenedora identificada por R.id.fragment_container. Llamando al método addToBackStack(), hacemos que se guarde el estado actual antes de aplicar el cambio.

Si añadimos más cambios en la transacción (añadir o borrar otro fragmento, por ejemplo) y llamamos al método addToBackStack(), esos cambios también se registrarán en la pila de retroceso.

Si añadimos múltiples fragmentos a una misma vista contenedora, el orden en el que son añadidos determinará el orden en el que aparecen en la vista.

Si no llamamos al método addToBackStack() cuando realizamos una transacción en la que se ha eliminado un fragmento, el fragmento será destruido cuando confirmemos la transacción y el usuario no podrá recuperar ese estado navegando hacia atrás. Si antes de confirmar los cambios, llamamos al método addToBackStack(), el fragmento será añadido a la pila de retroceso y será detenido. Cuando el usuario vuelva a él, será reanudado.

Truco. Para cada transacción con fragmentos, podremos realizar una animación llamando al método setTransition() antes de confirmar los cambios.

Que llamemos al método commit(), no significa que se realice la transacción justo en ese instante. Ésta pasa a ser programada para ser ejecutada en la hebra de la IU (hebra principal) tan pronto como ésta esté disponible. No obstante, y si es necesario, podemos llamar al método executePendingTransactions() desde la hebra de la IU para forzar la ejecución de las transacciones pendientes. Esto no será necesario, a menos que la transacción esté pendiente de trabajos realizados en otras hebras.

Importante. Podemos llamar al método commit() antes de que la actividad guarde su estado (cuando el usuario la abandona). Si intentamos confirmar la transacción después de este punto, se lanzará una excepción. Esto es debido a que el estado de la actividad se podría perder en el caso que ésta necesitase ser restaurada. Si el estado de la actividad no es importante para nosotros, podemos utilizar el método commitAllowingStateLoss() para confirmar la transacción.

Comunicación con nuestra actividad.

Aunque un fragmento se implementa como un objeto independiente de una actividad y puede ser usado dentro de otras actividades, la instancia de un fragmento está ligada a la actividad que lo contiene.

Un fragmento podrá acceder a la instancia de la actividad en la que está contenido usando su método getActivity() y así poder acceder de manera sencilla a los elementos de su plantilla:
View listView = getActivity().findViewById(R.id.list);
De la misma manera, una actividad puede obtener un fragmento determinado usando el gestor de fragmentos FragmentManager y utilizando sus métodos findFragmentById() o findFragmentByTag():
 ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);

Comunicando eventos a nuestra actividad.

En algunas ocasiones, necesitaremos que un fragmento comparta ciertos eventos con su actividad. Una buena manera de hacerlo es definiendo una interfaz de métodos retrollamada dentro del propio fragmento y obligar a que su actividad implemente dicha interfaz. Cuando la actividad recibe una retrollamada a través de la interfaz, ésta podrá compartir la información con otros fragmentos de la plantilla si fuera necesario.

Por ejemplo, si una aplicación de noticias tiene dos fragmentos en una actividad: uno que muestra un listado de artículos (fragmento A) y otro que muestra los detalles de un artículo (fragmento B), entonces el fragmento A debería avisar a la actividad cuando el usuario seleccionase un artículo y la actividad debería hacer que el fragmento B mostrase los detalles del artículo seleccionado. En este caso, declararemos la interfaz OnArticleSelectedListener (podríamos haber elegido otro nombre) dentro del fragmento A:
public static class FragmentA extends ListFragment {
    ...
    // La actividad contenedora debe implementar esta actividad
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...
}
Sería la actividad que alberga ambos fragmentos la encargada de implementar la interfaz OnArticleSelectedListener y sobreescribir el método onArticleSelected() para notificar al fragmento B del evento acaecido en el fragmento A. Para garantizar que la actividad implementa la interfaz, podemos usar el método retrollamada del fragmento A onAttach() (se llama a este método cuando el sistema añade el fragmento a la actividad), donde proyectaremos la actividad contenedora proporcionada por el método sobre la interfaz OnArticleSelectedListener:
public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " debe implementar la interfaz OnArticleSelectedListener");
        }
    }
    ...
}
Si la actividad no implementa la interfaz, el fragmento lanzará una excepción de tipo ClassCastException. Si todo ha ido bien, tendremos en la variable miembro mListener una referencia a la implementación de la interfaz OnArticleSelectedListener con la que el fragmento A puede compartir los eventos definidos en su interior. Por ejemplo, si el fragmento A es de tipo ListFragment, cada vez que el usuario pulse sobre un elemento de la lista, el sistema llamará al método onListItemClick() del fragmento, que a su vez llamará al método onArticleSelected() implementado en la actividad:
 public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Añadimos el ID del elemento seleccionado al URI base a los contenidos
        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
        // Enviamos el URI a la actividad utilizando su implementación
        mListener.onArticleSelected(noteUri);
    }
    ...
}
El parámetro id pasado al método onListItemClick() es el identificador de la fila seleccionada cuando un elemento es seleccionado. Este identificador es el que usará la actividad para obtener el artículo seleccionado a partir de nuestro propio proveedor de contenido.

Añadiendo elementos a la barra de acciones.

Un fragmento puede añadir sus propias opciones de menú a la barra de acciones de la actividad que la alberga implementando su método retrollamada onCreateOptionsMenu(). Para que este método sea invocado por el sistema, tendremos que llamar al método setHasOptionsMenu(true) desde el método onCreate() del fragmento. Esta es la manera de indicarle al sistema de que nuestro fragmento añadirá nuevos elementos al menú de la barra de acciones.

El fragmento también podrá hacer uso del método onOptionsItemSelected() que será llamado cada vez una opción de menú sea seleccionada.

También podremos registrar una vista en la plantilla del fragmento para proporcionar un menú contextual llamando al método registerForContextMenu(). Cuando el usuario abra el menú contextual, el fragmento recibirá una llamada a su método onCreateContextMenu(). Cuando el usuario seleccione una opción, se invocará el método onContextItemSelected().

Nota. El fragmento solo será consciente de que se ha seleccionado una opción de menú si ésta no ha sido previamente procesada por la actividad. Si la actividad no procesa la opción seleccionada, entonces se delega su proceso al fragmento.

Trabajando con el ciclo de vida de un fragmento.

Impacto del ciclo de vida de una actividad sobre el ciclo de vida de un fragmento
Imagen 3. Impacto del ciclo de vida de una actividad
sobre el ciclo de vida de un fragmento.
El ciclo de vida de un fragmento es muy parecido al ciclo de vida de una actividad. Como en una actividad, un fragmento puede estar en uno de los tres estados siguientes:
Reanudado
El fragmento es visible en la actividad que se está ejecutando.
Pausado
Otra actividad está en primer plano y tiene el foco, pero la actividad a la que pertenece el fragmento es aún visible (la actividad que está en primer plano es semi transparente o no ocupa toda la pantalla).
Detenido
El fragmento no es visible. Bien porque la actividad a pasado a estar detenida, o bien porque el fragmento fue eliminado y añadido a la pila de retroceso. Un fragmento detenido está aún vivo (su estado y variables miembro son conservadas por el sistema). No obstante, el usuario no podrá verlo y será eliminado si la actividad es eliminada.

También, como sucede con una actividad, puedes conservar el estado de un fragmento usando un objeto de tipo Bundle que podremos utilizar para su restauración en el caso en el que la actividad sea eliminada por el sistema. Podemos guardar el estado de un fragmento desde su método onSaveInstanceState() y recuperarlo desde los métodos onCrete(), onCreateView() o onActivityCreated().

La diferencia más importante entre el ciclo de vida de un fragmento y el ciclo de vida de una actividad es cómo se añaden a su propia pila de retroceso. Una actividad es añadida a su pila de retroceso de manera automática por el sistema. Por otro lado, una fragmento se añade su pila de retroceso, si lo hacemos de manera explícita desde la propia actividad a través del método addToBackStack(). Por lo demás, el ciclo de vida del fragmento es muy parecido al ciclo de vida de la actividad.

Importante. Si necesitamos acceder al contexto (Context) dentro de un fragmento, podemos hacerlo obteniendo su actividad con el método getActivity(). Sin embargo, tendremos que tener cuidado y asegurarnos de que el fragmento haya sido añadido a la actividad antes de invocarlo. Si no es así, el método devolverá null.

Sincronización con el ciclo de vida de la actividad.

El ciclo de vida de la actividad que alberga un fragmento, afecta al ciclo de vida de éste. Cada vez que el sistema llama a un método retrollamada del ciclo de vida de la actividad, implica una llamada similar para cada uno de los fragmentos que alberga. Por ejemplo, cuando el sistema invoca el método onPause() de la actividad, también se llamará a los métodos onPause() de los fragmentos contenidos.

Un fragmento cuenta con una serie de métodos retrollamada adicionales:
onAttach()
Se llama cuando el fragmento es añadido a la actividad.
onCreateView()
Se llama para crear la vista asociada al fragmento.
onActivityCreated()
Se llama justo después de finalizar el método onCreate() de la actividad.
onDestroyView()
Se llama cuando la vista asociada al fragmento se elimina.
onDetach()
Se llama cuando el fragmento ya no forma parte de su actividad.

El ciclo de vida de un fragmento, está influenciado por la actividad que lo alberga (ver imagen 3). En la imagen podemos observar como cada estado de la actividad determina qué métodos del fragmento serán invocados. Por ejemplo, cuando la actividad recibe una llamada a su método onCreate(), el fragmento recibirá una serie de llamadas adicionales previas a onActivityCreated().

Una vez la actividad alcanza su estado reanudada (en ejecución), podremos añadir y eliminar fragmentos a nuestro antojo. Solo cuando la actividad se encuentra reanudada, el ciclo de vida de un fragmento podrá cambiar de manera independiente. Sin embargo, una vez que la actividad abandona el estado reanudada, el fragmento se verá obligado a cambiar con ella.

No hay comentarios:

Publicar un comentario