diegoRodicio

View Categories

🔄 StatefulWidget e setState

🔁 Widgets con estado: StatefulWidget

Un StatefulWidget é un widget que utilizamos cando necesitamos gardar información que pode cambiar durante o funcionamento da aplicación e actualizar a pantalla para mostrar eses cambios.

Por exemplo, imaxina unha aplicación cun contador:

  1. Ao abrir a aplicación, o contador mostra o número 0.
  2. Cando prememos un botón, o contador aumenta a 1.
  3. Se volvemos premer, aumenta a 2, e así sucesivamente.

Neste caso, o número do contador é o estado, porque é un dato que vai cambiando. Cada vez que cambia, a pantalla actualízase para mostrar o novo valor.

Utilizamos StatefulWidget en situacións como estas:

  • Contadores: un número que aumenta ou diminúe ao premer un botón.
  • Cronómetros: o tempo que aparece na pantalla cambia automaticamente cada segundo.
  • Formularios: podemos gardar a información introducida polo usuario e mostrar cambios na pantalla.
  • Mostrar ou ocultar elementos: por exemplo, un botón que permite mostrar ou esconder un contrasinal.

Flutter tamén proporciona widgets con estado que podemos utilizar nas nosas aplicacións:

  • Checkbox: unha caixa que podemos marcar ou desmarcar.
  • TextField: un campo no que podemos escribir e modificar texto.
  • Switch: un interruptor que podemos activar ou desactivar.
  • Slider: unha barra que podemos mover para seleccionar un valor.

En Checkbox, Switch e Slider, o valor seleccionado recíbese mediante value. Normalmente, o pai garda ese valor e actualízao cando recibe o aviso de onChanged.

💡 Cando usalos? Cando necesitamos que un widget garde información que pode cambiar e actualice a pantalla para mostrar eses cambios.

🔢 Un contador que cambia

Imos crear unha aplicación cun contador que comeza en 0. Cada vez que prememos o botón Sumar 1, o contador aumenta e a pantalla mostra o novo valor.

Para conseguilo, utilizaremos un StatefulWidget.

🔗 DartPad:

Contador que actualiza a pantalla con setState
Contador que actualiza a pantalla con setState

💡 Truco: En VS Code podemos escribir stful para crear automaticamente a estrutura básica dun StatefulWidget, incluídas as dúas clases que necesitamos.

Crear un StatefulWidget co atallo stful de VS Code
Crear un StatefulWidget co atallo stful de VS Code

🧩 Por que hai dúas clases?

Ao crear un StatefulWidget, Flutter necesita dúas clases que traballan xuntas: unha para definir o widget e outra para xestionar a información que pode cambiar.

No noso exemplo:

  • PantallaContador: é a clase que representa o widget. A súa función principal é crear e asociar o estado que utilizará.
  • _PantallaContadorState: é a clase que garda o valor do contador, permite incrementalo e constrúe a interface que vemos na pantalla.

Podemos resumir as súas funcións nesta táboa:

ClasePara que serve?
PantallaContador (StatefulWidget)Define o widget e utiliza createState() para crear o seu estado.
_PantallaContadorState (State<PantallaContador>)Garda os datos que poden cambiar, contén os métodos para modificalos e utiliza build() para construír a interface.

Por que non gardamos todo na mesma clase?

Porque os widgets de Flutter son inmutables, é dicir, os seus atributos non se poden modificar unha vez creados.

Por iso, Flutter utiliza unha segunda clase (State) para gardar a información que pode cambiar sen necesidade de crear un estado novo cada vez que se actualiza a pantalla.

No exemplo do contador, a variable _contador pertence á segunda clase. Así, cando prememos Sumar 1, o seu valor aumenta e a pantalla mostra o novo número.

As dúas clases: configuración no StatefulWidget e datos mutables no State
As dúas clases: configuración no StatefulWidget e datos mutables no State

💡 Lembra que o símbolo _ ao principio dun nome indica que é privado dentro da biblioteca de Dart, como vimos no Tema 2.2.

🔄 Que fai setState()?

Cando modificamos un dato dun StatefulWidget, necesitamos indicarlle a Flutter que debe actualizar a pantalla para mostrar o novo valor.

Para iso utilizamos setState(), un método que permite modificar os datos e avisar a Flutter de que debe actualizar a interface.

No exemplo do contador, cando prememos o botón Sumar 1, sucede o seguinte:

  1. Execútase o método _incrementar().
  2. Dentro de setState(), aumentamos o valor de _contador en 1.
  3. Flutter volve executar o método build() para actualizar a pantalla co novo valor.

Observa o código:

void _incrementar() {
  setState(() {
    _contador++;
  });
}

Incrementar o contador e actualizar a interface con setState
Incrementar o contador e actualizar a interface con setState

Que pasaría se non utilizásemos setState()?

Se modificamos _contador sen utilizar setState(), o valor da variable cambiaría, pero Flutter non recibiría o aviso de que debe actualizar a pantalla. Polo tanto, o novo valor podería non aparecer inmediatamente.

💡 Lembra: setState() avisa a Flutter de que cambiou información que afecta á interface e que debe actualizala.

📌 Onde debemos gardar os datos que cambian?

No noso exemplo, declaramos a variable _contador dentro da clase _PantallaContadorState, pero fóra do método build():

int _contador = 0; // Dentro do State, pero fóra de build.

Isto é importante porque o método build() pode executarse moitas veces durante o funcionamento da aplicación.

Se declaramos _contador dentro de build(), a variable volvería inicializarse a cero cada vez que se executase ese método. Por exemplo, ao actualizar a pantalla despois de premer o botón, perderiamos o valor anterior do contador.

Ao declarala fóra de build(), o seu valor consérvase entre as actualizacións da pantalla.

Gardar o contador no State, fóra do método build
Gardar o contador no State, fóra do método build

📚 Consulta: