Stateless x Stateful

Entenda a diferença e saiba quando utilizar cada um deles.

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();
}
}
  1. Criamos um widget extendendo StatelessWidget.

  2. 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();
}
}
  1. Criamos um widget extendendo StatefulWidget.

  2. Nosso widget, através da função createState(), retorna o widget WidgetComEstadoState. (lembrando que o "_" faz com que o objeto seja privado).

  3. 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.

  4. 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,
);
}
}
  1. Adicionamento a informação _tamanho ao nosso widget.

  2. Criamos as funções aumentar() e diminuir().

  3. Em cada uma delas, alteramos a informação e chamamos a função setState.

  4. Assim, quando as funções aumentar() e diminuir() forem chamadas, a informação tamanho será atualizada e com a execução da função setState, 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.