🔁 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:
- Ao abrir a aplicación, o contador mostra o número 0.
- Cando prememos un botón, o contador aumenta a 1.
- 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:

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

🧩 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:
| Clase | Para 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.

💡 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:
- Execútase o método
_incrementar(). - Dentro de
setState(), aumentamos o valor de_contadoren 1. - Flutter volve executar o método
build()para actualizar a pantalla co novo valor.
Observa o código:
void _incrementar() {
setState(() {
_contador++;
});
}

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.

📚 Consulta: