> For the complete documentation index, see [llms.txt](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion.md).

# Ciclo de vida de la aplicación

En una aplicación Flutter, tendremos acceso a una selección de los **eventos** del **ciclo** de **vida** de la **aplicación** (en una app nativa tendríamos más eventos).

## Estados

Los diferentes **estados** en los que puede estar la aplicación (ciclo de vida) vienen determinados por el `enum` [`AppLifecycleState`](https://api.flutter.dev/flutter/dart-ui/AppLifecycleState.html) y son los siguientes:

* **detached**:  La aplicación **no tiene interfaz visible**, está en proceso de creación/destrucción (***Destroyed*** de Android).
* **resumed**:  La aplicación está **visible** e **interactuando** con el usuario.  (***Resumed*** de Android)
* **inactive**: La aplicación es **visible** **pero** **no** **recibe** **interacción** del usuario: split-screen, un diálogo del sistema aparece, una llamada de teléfono,..   (Sería similar a un estado ***Paused*** de Android)
* **hidden:**  La aplicación **no** es **visible,** está a punto de ser pausada.
* **paused**: La aplicación **no** es **visible**, está en segundo plano, y **no** **interactúa** con el usuario.  (***Stopped*** de Android)

## Eventos del ciclo de vida

Podemos **capturarlos** de dos formas:

* Utilizando la clase abstracta  **`WidgetsBindingObserver`** como ***mixin***&#x20;
* Utilizando un objeto **`AppLifecycleListener`**  &#x20;

### Primera forma: **`WidgetsBindingObserver`**&#x20;

Para **capturar** los **eventos** del ciclo de vida de la aplicación:

* Utilizaremos la **clase** **abstracta** **`WidgetsBindingObserver`** como ***mixin*** que nos permitirá observar los eventos del ciclo de vida y sobrescribir solo los métodos que nos interesen (el mixin no obliga a sobrescribir todos los métodos,  al contrario que si se implementa una interfaz)
* **Sobrescribiremos** el método **`didChangeAppLifecycleState(...)`** que se llamará cuando haya un cambio de estado en la aplicación.

{% hint style="danger" %}
La gestión del ciclo de vida de la aplicación debe realizarse en un `StatefulWidget`, que es el único que proporciona los métodos de ciclo de vida (initState y dispose) necesarios para hacerlo de forma segura y sin fugas de memoria.
{% endhint %}

<details>

<summary><strong>Ejemplo 1:</strong> Código....</summary>

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with WidgetsBindingObserver {

  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  // WidgetsBindingObserver.
  // Called when the system puts the app in the background 
  // or returns the app to the foreground.
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print('State: ${state.name}');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter - Lifecycle'),
      ),
      body: Center(),
    );
  }
}
```

</details>

{% hint style="info" %}
**WidgetsBinding** és la **clase** **central** que actúa com el **vínculo** entre el framework Flutter y el motor Flutter subyacente.  Es un **objeto** **singleton**, `WidgetsBinding.instance`y se encarga, entre otros de la supervisión del ciclo de vida,  coordinar el renderizado correcto de los widgets, hacer llegar los eventos de entrada como gestos y toques a los widgets adecuados, accesibilidad, etc.&#x20;
{% endhint %}

Los **cambios** de **estado** los podemos **comprobar** en el **Logcat** cuando, por ejemplo realizamos las siguientes **acciones**:

1. Dejamos la aplicación en segundo plano:  **inactive -> hidden -> paused**
2. Luego, volvemos a ella:  **hidden -> inactive -> resumed**
3. Finalmente, cerramos la aplicación:  **inactive ->** **hidden -> paused -> detached**

> **Ejemplo de filtro Logcat:**&#x20;
>
> ```
> level:info   message: State:  package:com.example.ejemplo_flutter
> ```

<figure><img src="/files/O2IKRWIsAMfPM8J2VKBJ" alt="" width="166"><figcaption></figcaption></figure>

### Segunda forma:  Usando un objeto **AppLifecycleListener**&#x20;

Este es el **enfoque más moderno y recomendado** para escuchar los cambios en el ciclo de vida de la aplicación.

Para ello, **añadiremos** un objeto de la clase **`AppLifecycleListener`** y así podremos:

* **Escuchar las transiciones** entre estados: **que nos interesen,** y también,
* **Escuchar** siempre **cualquier** **cambio** de **estado**.&#x20;

<figure><img src="/files/JJ5XxJ00NfYQPyBQOotq" alt="" width="563"><figcaption><p><a href="https://api.flutter.dev/flutter/widgets/AppLifecycleListener-class.html">https://api.flutter.dev/flutter/widgets/AppLifecycleListener-class.html</a></p></figcaption></figure>

El **estado** **inicial** es el estado [AppLifecycleState.detached](https://api.flutter.dev/flutter/widgets/dart-ui/AppLifecycleState.html).   Las flechas describen transiciones de estado **válidas**.&#x20;

* Las transiciones en <mark style="color:blue;">**azul**</mark> son **transiciones** que solo ocurren en **iOS** y **Android**.

<details>

<summary><strong>Ejemplo 2:</strong> Código....</summary>

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late final AppLifecycleListener _myAppStateListener;

  @override
  void initState() {
    super.initState();
    // Ahora indicamos qué transiciones queremos escuchar de forma individual
    _myAppStateListener = AppLifecycleListener(
      onDetach: () => print('Event: onDetach'),
      onShow: () => print('Event: onShow'),
      onHide: () => print('Event: onHide'),
      onInactive: () => print('Event: onInactive'),
      onPause: () => print('Event: onPause'),
      onRestart: () => print('Event: onRestart'),
      onResume: () => print('Event: onResume'),

      // Escuchamos también cualquier cambio de estado
      onStateChange: (state) => print('State: ${state.name}'),
    );
  }

  @override
  void dispose() {
    _myAppStateListener.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter - Lifecycle - AppLifecycleListener'),
      ),
      body: Center(
          child: Text('To observe states and lifecycle events: \n'
          'Change device orientation, hide application, return back...\n ')
      ),
    );
  }
}
```

</details>
