diegoRodicio

View Categories

📥 Devolver un dato ao pechar a pantalla

📝 Devolver datos ao pechar unha pantalla

No apartado anterior aprendemos a utilizar un callback para comunicar un cambio desde unha pantalla secundaria á principal.

Pero Flutter tamén permite facelo doutra maneira: a segunda pantalla pode devolver un dato cando se pecha.

Para comprendelo, imaxinemos unha aplicación cun contador:

  • A pantalla principal mostra o valor do contador.
  • Ao premer «Editar», abrimos outra pantalla e enviámoslle o valor actual.
  • Na segunda pantalla podemos aumentar o contador.
  • Se prememos «Gardar», devolvemos o novo valor á pantalla principal.
  • Se prememos «Cancelar» ou volvemos coa frecha, descartamos os cambios e o contador orixinal non cambia.
Edición dun contador nunha segunda pantalla
Edición dun contador nunha segunda pantalla

Neste caso non necesitamos pasar unha función como callback. A pantalla principal esperará a que se peche a segunda pantalla para recibir o resultado.

O funcionamento será o seguinte:

Principal: _contador = 0
   ↓ Abrimos o editor enviando o valor 0
Editor: _valor = 0 → «Sumar 1» → _valor = 1
   ↓ «Gardar» devolve o valor 1
Principal: recibe 1 → setState → mostra 1

📤 Enviar o valor ao editor

A pantalla principal garda o contador na variable _contador.

Cando abrimos o editor, enviámoslle ese número mediante o parámetro valorInicial do construtor:

EditorContador(valorInicial: _contador)

O editor recibe o número e declárao como un atributo:

final int valorInicial;

Como o editor é un StatefulWidget, necesitamos unha variable dentro do seu State para modificar o contador sen cambiar o valor orixinal.

Para iso declaramos _valor e inicializámola en initState:

late int _valor;

@override
void initState() {
  super.initState();
  _valor = widget.valorInicial; // Comezamos co valor recibido.
}

Neste código:

  • late int _valor declara a variable que utilizaremos para modificar o contador. late permite inicializala posteriormente.
  • widget.valorInicial permite acceder desde o State ao dato recibido polo construtor.
  • initState() inicializa _valor unha soa vez, cando se crea o estado do editor.

Deste xeito, podemos modificar _valor sen cambiar _contador.

O contador da pantalla principal só cambiará cando gardemos e devolvamos o novo valor.

📥 Esperar o resultado coa instrución await

Cando abrimos unha pantalla con Navigator.push(), podemos esperar a que se peche e recoller o valor que devolva.

Para iso utilizamos await:

final resultado = await Navigator.push<int>(
  context,
  MaterialPageRoute<int>(
    builder: (context) => EditorContador(valorInicial: _contador),
  ),
);

Nesta instrución:

  • Navigator.push() abre a pantalla do editor.
  • await espera a que esa pantalla se peche para continuar coa seguinte instrución.
  • <int> indica que esperamos recibir un número enteiro.
  • resultado é a variable na que gardaremos o valor devolto polo editor.

Para poder utilizar await, o método que o contén debe declararse con async:

Future<void> _editar() async {
  // Código para abrir o editor e esperar o resultado.
}

💡 await non bloquea a aplicación. Mentres esperamos o resultado, podemos utilizar normalmente a segunda pantalla. Cando esta se pecha, continúa a execución do método.

Future<void> indica que o método é asíncrono e que non devolverá ningún valor propio. Polo momento, abonda con saber que utilizamos async e await para esperar o resultado dunha operación.

🔄 Actualizar o contador ao volver

Cando o editor se pecha, a execución continúa despois de await e podemos utilizar o valor recibido.

Antes de actualizar o contador comprobamos que recibimos un resultado válido:

if (!mounted || resultado == null) return;

Nesta comprobación:

  • resultado == null indica que a pantalla se pechou sen devolver un valor, por exemplo, ao volver sen gardar.
  • !mounted evita actualizar a pantalla principal se esta xa foi eliminada.

Se algunha destas condicións se cumpre, saímos do método sen modificar o contador.

En caso contrario, actualizamos o valor mediante setState():

setState(() {
  _contador = resultado;
});

Deste xeito, o contador da pantalla principal recibe o novo valor e a interface actualízase.

↩️ Gardar ou cancelar desde o editor

Na segunda pantalla temos dous botóns que permiten gardar os cambios ou cancelar a edición.

Gardar os cambios

Ao premer «Gardar», executamos:

Navigator.pop(context, _valor);

Esta instrución fai dúas cousas:

  • Pecha a pantalla do editor.
  • Devolve o valor de _valor á pantalla principal, que estaba esperando o resultado mediante await.

Cancelar os cambios

Ao premer «Cancelar», executamos:

Navigator.pop(context);

Neste caso, a pantalla péchase sen devolver ningún valor. O mesmo sucede se utilizamos a frecha de volver da barra superior.

Polo tanto, resultado será null e o contador da pantalla principal non cambiará.

💡 Fíxate na diferenza: Navigator.pop(context, _valor) pecha a pantalla devolvendo un dato, mentres que Navigator.pop(context) péchaa sen devolver ningún valor.

Neste mecanismo non necesitamos pasar un callback. O editor devolve un valor ao pecharse e a pantalla principal decide como utilizalo.

🧪 Exemplo completo

🔗 DartPad:

Envío do contador ao editor e devolución do resultado con await
Envío do contador ao editor e devolución do resultado con await

🔍 Que sucede ao editar o contador?

Imos seguir o funcionamento do programa paso a paso:

  1. A pantalla principal mostra o contador co valor 0, porque _contador = 0.
  2. Prememos «Editar» e abrimos EditorContador, enviándolle o valor 0 mediante valorInicial.
  3. O editor recibe ese número e gárdao na súa variable _valor.
  4. Prememos «Sumar 1» dúas veces, polo que _valor pasa a valer 2.
  5. Ao premer «Gardar», executamos Navigator.pop(context, _valor) e devolvemos o número 2.
  6. A pantalla principal recibe ese número na variable resultado, despois da instrución await.
  7. Finalmente, setState() actualiza _contador e a pantalla mostra «Valor: 2».

💡 Fíxate: se volvemos coa frecha sen premer «Gardar», non devolvemos ningún número. Neste caso, resultado será null e o contador da pantalla principal conservará o seu valor anterior.

🧪 Comproba o funcionamento

Executa o programa e realiza estas probas:

  1. Abre o editor, preme «Sumar 1» dúas veces e garda. O contador principal debe mostrar 2.
  2. Volve abrir o editor. Comproba que o valor inicial agora é 2.
  3. Preme «Sumar 1» tres veces, pero volve coa frecha sen gardar. O contador principal debe seguir mostrando 2.

Deste xeito comprobamos que podemos modificar un dato nunha segunda pantalla sen cambiar o orixinal ata que decidamos gardalo.

📚 Consulta: