Olá Habr! Apresentando uma tradução do artigo,
deixe-me ajudá-lo a entender e escolher uma solução de gerenciamento de estado para seu aplicativo , que chamou minha atenção e se interessou no processo de aprender os conceitos básicos de gerenciamento de estado em Flutter. Ficarei feliz em ouvir críticas sobre esta tradução. Nas aspas (``) serão escritos meus pensamentos e explicações pessoais.

Gerenciamento de estado de vibração é um tópico importante. Existem muitas soluções possíveis para o problema e, confundindo-se com elas, a escolha da mais adequada às suas necessidades é extremamente simples. Eu mesmo estava confuso, mas encontrei uma solução adequada. Deixe-me compartilhar com você.
Para encontrar uma solução que atenda às suas necessidades, você precisa determinar as próprias necessidades. No meu caso, é o seguinte:
- Ter a oportunidade de desenvolver o projeto sem comprometer a qualidade do código
- Separe a lógica de exibição da lógica de negócios
- Tenha um código claro e difícil de quebrar
- Previsibilidade e compreensibilidade do código
Atendendo a esses requisitos, permanecem opções adequadas:
- Usando o método
setState()
e Widgets com Estado - ScopedModel `Library`
- Usando o padrão BLoC (Business Logic Components)
- Redux
A diferença entre estado local e global
Antes de mergulhar na análise das soluções selecionadas, você precisa entender a diferença entre o estado local e o global. Um exemplo prático é adequado para isso:
Imagine um formulário de autorização, em que o usuário é solicitado a inserir um nome de usuário e senha e obter o objeto "identidade do usuário" após o envio do formulário. Neste exemplo, qualquer verificação dos dados inseridos nos campos do formulário fará parte do estado local do `widget de formulário de autorização ', e o restante do aplicativo não deve estar ciente disso. E o objeto "identidade" retornado pelo "servidor de autorização" faz parte do estado global. Portanto, outros componentes dependem desse objeto, alterando o comportamento, dependendo se o usuário está autorizado.
Breves conclusões para quem está cansado de esperarSe você não quiser esperar ou não estiver interessado em minha pesquisa, aqui está uma breve visão geral dos resultados:

Minha recomendação é usar o BLoC para gerenciamento de estado local e o Redux para o estado global, especialmente se você estiver criando um aplicativo complexo que crescerá com o tempo.
Por que você não deve usar setState ()
O uso de
setState()
dentro de seus widgets é ótimo para prototipar rapidamente e obter feedback sobre essas alterações, mas dessa maneira não nos ajuda a alcançar nossos objetivos, porque a lógica de exibição é misturada à lógica de negócios, o que viola o princípio de limpeza e qualidade do código. A manutenção desse código será difícil no futuro; portanto, exceto para a criação de protótipos, essa abordagem não é recomendada.
ScopedModel - um passo na direção certa
ScopedModel é uma biblioteca de terceiros de
Brian Egan . Isso possibilita a criação de objetos
Models
especiais, além de usar o método
notifyListeners()
quando necessário. Por exemplo, para rastrear qualquer alteração nas propriedades de um objeto de modelo:
class CounterModel extends Model { int _counter = 0; int get counter = _counter; void increment() { _counter++; notifyListeners(); } }
Em nossos widgets, poderemos responder a alterações no modelo usando o widget
ScopedModelDescendant
`fornecido por esta biblioteca
ScopedModelDescendant
:
class CounterApp extends StatelessWidget { @override Widget build(BuildContext context) { return new ScopedModel<CounterModel>( model: new CounterModel(), child: new Column(children: [ new ScopedModelDescendant<CounterModel>( builder: (context, child, model) => new Text('${model.counter}'), ), new Text(" , CounterModel") ]) ); } }
Ao contrário do uso da abordagem
setState()
, esta solução permite separar a lógica de exibição da lógica de negócios. No entanto, impõe certas restrições:
- Se o
Model
se tornar complexo, fica difícil determinar quando usar o método notifyListeners()
e, quando não, evitar atualizações desnecessárias da interface. - A API fornecida pelo
Model
, em geral, não descreve com precisão a natureza assíncrona da interface do aplicativo
Dado tudo isso, se o estado do seu aplicativo não for fácil de gerenciar, não recomendo usar essa abordagem de dados. Só não acredito que ele seja capaz de fornecer produtivamente o crescimento e a complexidade dos aplicativos.
Solução poderosa - BLoC
Esse padrão foi inventado pelo Google e também é usado lá. Ele nos ajudará a alcançar os seguintes objetivos:
- Separação da lógica de exibição da lógica de negócios
- Usando natureza assíncrona para exibir uma interface
- A capacidade de reutilizar em diferentes aplicativos Dart, como Flutter ou AngularDart
A ideia por trás dessa abordagem é muito simples:
- Utiliza BLoC
Sink<T>
API para descrever a entrada assíncrona de nossos componentes de dados - Utiliza BLoC
Stream<T>
API para descrever dados retornados de forma assíncrona por nossos componentes - Por fim, podemos usar o widget
StreamBuilder
para controlar fluxos de dados, sem StreamBuilder
nenhum esforço de nossa parte para assinar atualizações de dados e redesenhar widgets
O Google tem bons exemplos de uso desse padrão de gerenciamento de estado, pois é amplamente usado e altamente recomendado pela empresa.
Eu próprio recomendo usar esta abordagem para gerenciar o estado local, mas é até adequada para gerenciar o estado global. No entanto, no último caso, você encontrará um problema - onde e como implementar corretamente o BLoC para que diferentes componentes tenham acesso a ele e, em seguida, o Redux entra em cena.
Redux e BLoC - a mistura perfeita para mim
Um dos objetivos que descrevi no início do artigo era encontrar algo amplamente usado e previsível, e esse é o Redux - um padrão e um conjunto de ferramentas que juntos nos ajudam a gerenciar o estado global. Ele tem três princípios básicos no núcleo:
A única fonte de verdade é que todo o estado do
state
seu aplicativo é armazenado em um objeto de árvore em um único
store
- O estado é somente leitura - a única maneira de alterar o estado é chamar um objeto de ação especial que descreva o que deve acontecer com o estado
- As alterações são feitas usando funções puras - para determinar quais alterações de estado, você escreve a função pura '
reducer
, que não deve causar efeitos colaterais` Link para o código de exemplo`
Link para a postagem original, de onde a imagem vemEssa abordagem para gerenciar o estado é amplamente aceita pelos desenvolvedores da Web, e sua aparência em dispositivos móveis ajudará a beneficiar os desenvolvedores da Web e de aplicativos móveis.
Brian Egan está desenvolvendo o
Redux original e o
flutter_redux , e também criou um
aplicativo Todo incrível
, no qual aplicou muitos padrões arquiteturais, incluindo o Redux.
Dadas todas as qualidades do Redux, recomendo fortemente usá-lo para gerenciar o estado global, mas você deve ter certeza de que não o usa para gerenciar o estado local, se desejar dimensionar seu aplicativo.
Últimas palavras
Não há solução completamente correta ou incorreta neste artigo. Para decidir qual abordagem aplicar em seu projeto, você precisa decidir sobre suas necessidades. Para mim e meus objetivos, a combinação de Redux e BLoC permite que meus projetos cresçam com rapidez e segurança, além de facilitar a entrada de desenvolvedores de terceiros nesses projetos, graças a ferramentas acessíveis e claras. No entanto, nem todos têm as mesmas necessidades e, com o tempo, você pode encontrar problemas 'nas ferramentas atuais' e soluções ainda melhores. É muito importante permanecer sempre curioso, aprender e pensar se essa ou aquela ferramenta é adequada para você.