Stateless x Stateful
Já disse anteriormente que no Flutter temos apenas 2 tipos de widgets:
Stateless: Um widget que não tem seu estado alterado.
- Um texto, é um widget que não tem seu estado alterado.
Stateful: Um widget que tem seu estado alterado.
- Um switch, é um widget que tem seu estado alterado.
Por definição, na própria documentação da API, temos:
Um widget é uma descrição imutável de parte de uma interface de usuário
Como assim?! Dois tipos, mutável e não mutável, e a API explicitamente nos dizendo que é imutável?
Vamos lá!
A documentação complementa com a seguinte afirmação:
Widgets por si só, não possuem estado mutável (todos os campos devem ser final). Se precisar associar um estado mutável a um widget, considere utilizar o StatefulWidget, que cria um objeto do tipo State...
Logo, podemos assumir que com o objeto State, o widget do tipo StatefulWidget torna-se mutável.
Vamos para o código que as coisas ficarão mais fáceis:
StatelessWidget
class WidgetSemEstado extends StatelessWidget {
Widget build(BuildContext context) {
return FlutterLogo();
}
}
- Criamos um widget extendendo StatelessWidget.
- Nosso widget retorna um FlutterLogo widget.
StatefulWidget
class WidgetComEstado extends StatefulWidget {
_WidgetComEstadoState createState() {
return _WidgetComEstadoState();
}
}
class _WidgetComEstadoState extends State<WidgetComEstado> {
Widget build(BuildContext context) {
return FlutterLogo();
}
}
- Criamos um widget extendendo StatefulWidget.
- Nosso widget, através da função
createState()
, retorna o widget WidgetComEstadoState. (lembrando que o "_" faz com que o objeto seja privado). - Como o widget WidgetComEstadoState extende de um objeto do tipo State, conseguimos armazenar informações, que podem ser lidas e atualizadas. E com este objeto, temos acesso ao método setState(), que quando é executado, faz com que o nosso widget seja reconstruído. Ou seja, ao atualizarmos uma informação, executarmos o método setState, o nosso widget é reconstruído com a informação atualizada.
- O widget WidgetComEstadoState retorna um FlutterLogo widget.
Agora que já sabemos a teoria, vamos para a prática e implementar os benefícios que o objeto State proporciona ao widget.
class _WidgetComEstadoState extends State<WidgetComEstado> {
var _tamanho = 32.0;
void aumentar() {
setState(() {
_tamanho = _tamanho + 16;
});
}
void diminuir() {
setState(() {
_tamanho = _tamanho - 16;
});
}
Widget build(BuildContext context) {
return FlutterLogo(
size: _tamanho,
);
}
}
- Adicionamento a informação
_tamanho
ao nosso widget. - Criamos as funções
aumentar()
ediminuir()
. - Em cada uma delas, alteramos a informação e chamamos a função
setState
. - Assim, quando as funções
aumentar()
ediminuir()
forem chamadas, a informação tamanho será atualizada e com a execução da funçãosetState
, o nosso widget será reconstruído, já contemplando o novo valor de_tamanho
.
Veja o código acima em ação no DartPad.
Ainda há espaço nos aprofundarmos neste assunto, mas por hora, entender esta básica diferença entre os tipos de widgets já é o suficiente.