Gerenciamento de Estado com GetX no Flutter
O get, e não get_it, é um pacote muito completo, contendo os três pilares ( Gerenciamento de Estado, Gerenciamento de Rotas e Gerenciamento de Dependências ).
Ele conta com outras diversas soluções, como um cliente http GetConnect, utilidades GetUtils e etc...
Porém nós iremos falar sobre o GetxController, existem algumas formas de fazer o gerencimento de estado com o get, podemos optar pelo reativo ou simples.
Hoje, iremos abordar o mais simples. Então vamos lá, depois de você ter instalado o get no seu projeto no arquivo pubspec.yaml podemos ir diretamente para o código.
Vamos utilizar o código padrão de boas-vindas do Flutter, o contador.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Contador',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Aqui temos uma estrutra simples, não vou explicar pois se você desenvolve em Flutter, só deve entrar nesse assunto de Gerenciamento de Estado mais profundo depois de ter entendido bem o próprio setState.
Pois é, se você não sabe o que é esse código acima, aconselho voltar um pouco para entender melhor a estrutura de Widgets do Flutter.
Então vamos lá. Podemos criar um controlador para gerenciar esse contador.
class Controller extends GetxController {
}
Note que na hora de fazer a importação, aparecerá várias formas de importar, isso acontece pois o get é desacoplado na questão de funcionalidades. veja na documentação:
GetX não está inchado. Ele possui uma infinidade de recursos que permitem começar a programar sem se preocupar com nada, mas cada um desses recursos fica em containers separados e só são iniciados após o uso. Se você usar apenas o gerenciamento de estado, apenas o gerenciamento de estado será compilado. Se você usar apenas rotas, nada do gerenciamento de estado será compilado.
Agora, vamos tirar a variável _counter e o método _incrementCounter da nosso _MyHomePageState.
Simplesmente precisamos movê-los para o nosso Controller, ficando assim:
class Controller extends GetxController {
int counter = 0;
void incrementCounter() {
setState(() {
counter++;
});
}
}
Pronto! A única mudança que fiz ai, foi tirar os "_" para poder acessar a variável e o método na View ( Claro que foi só para facilitar, mas teria como usar os getters e setters tranquilamente ).
Agora temos um problema! O setState depende de um State, e nós não temos mais esse State, a solução é muito simples, basta tirarmos ele e trocar por um update()
class Controller extends GetxController {
int counter = 0;
void incrementCounter() {
counter++;
update();
}
}
Simples né? Agora, só falta mudar a View, vamos fazer isso agora.
// ...
class _MyHomePageState extends State<MyHomePage> {
final controller = Get.put(Controller());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times:',
),
GetBuilder<Controller>(
builder: (_) {
return Text(
'${controller.counter}',
style: Theme.of(context).textTheme.headlineMedium,
);
}
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Agora podemos testar! Você verá o contador sendo incrementado perfeitamente.
Nós precisamos registrar o nosso Controller, eu fiz isso usando o Get.put, eu poderia usar o init do GetBuilder que também funcionaria.
Depois eu envolvi o Text em um GetBuilder que é o responsavel por reconstruir o Widget em uma atualização.
É importante tipar, GetBuilder< Seu tipo aqui >.
No builder dele, temos acesso a instância do próprio Controller, então poderiamos usar ele para acessar a variável ou o método.
Por fim, retornamos o Widget e com apenas isso, temos um gerenciamento de estados utilizando o GetX! :)
É realmente muito interessante o GetX, usei bastante num primeiro projeto que trabalhei com Flutter.
Só que entram daí problemas relacionados a manter toda a sua aplicação dependente de um Package né...
Adoro o jeito que o GetX faz as injeções de Dependências e Reatividade na UI.
Porém, o momento que pararem por exemplo de dar suporte ao Package, ou que você precisar modificar o projeto para outra ferramente, vai dar problema.
Ainda mais quando novos Devs entrarem, que vão ficar muito apegados ao Package, e acabando fechando as ideias criativas, por apenas terem conhecimento dele e quererem usar em tudo.
Não recomendo GetX para iniciantes. Acaba apenas dificultando o entendimento de como o Flutter funciona.