Orientação gerada a partir de informações públicas. Apenas para referência.
Fountain é um pacote Flutter projetado para injeção de dependência e gerenciamento de estado, oferecendo uma maneira limpa e eficiente de gerenciar dependências e estado compartilhado em toda a aplicação. Construído com simplicidade em mente, permite que desenvolvedores registrem e recuperem facilmente serviços, widgets e outros componentes ao longo do ciclo de vida do aplicativo. O pacote suporta todas as principais plataformas, incluindo Android, iOS, Web, macOS, Windows e Linux, tornando-o ideal para projetos multiplataforma. Com pouco código boilerplate e sintaxe intuitiva, Fountain simplifica o processo de desenvolvimento, mantendo desempenho e escalabilidade.
Casos de uso
Desenvolvimento de aplicativos multiplataforma
Gerenciando estado compartilhado
Injeção de dependência em aplicativos grandes
Simplificação do registro de serviço
Testando com dependências fictícias
Principais recursos
Boilerplate mínimo
Design independente de plataforma
Registro fácil de serviço
Gerenciamento de ciclo de vida embutido
Suporte para mocking em testes
Indicado para
Desenvolvedores Flutter em busca de DI leve
Projetos que exigem gerenciamento de estado escalonável
Equipes priorizando testabilidade
Aplicativos direcionados a múltiplas plataformas
Desenvolvedores evitando soluções complexas de estado
Considerações
Documentação limitada em comparação com alternativas maduras
Tamanho menor da comunidade
Pode exigir curva de aprendizado para novos usuários
Não adequado para cenários de estado muito complexos
Mais adequado para aplicativos de médio a grande escala
README original
Snapshot do README original do repositório-fonte vinculado. Consulte o repositório para o conteúdo mais recente.
The modular state management solution for flutter.
Easy debugging : each event is predictable and goes into a single pipeline
Centralized state : solid state validation
Power of async generators : writing asynchronous code is easy thanks to Dart generators
The view that subscribes to the state changes and dispatches actions :
classMyHomePageextendsStatelessWidget{
MyHomePage({Key? key}) : super(key: key);
@overrideWidgetbuild(BuildContext context) {
returnScaffold(
appBar: AppBar(
title: Text('Flutter Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Builder(
builder: (context) {
/// This widget will be rebuilt each time the `count` value changesfinal count =
context.select((CounterState state) => state.count);
returnText(
'$count',
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: Builder(
builder: (context) {
/// This widget will be rebuilt each time the `isMax` value changesfinal isMax = context.select((CounterState state) => state.isMax);
if (isMax) {
returnFloatingActionButton(
/// The action is executed in the [ApplicationContext].
onPressed: () => context.dispatch<CounterState>(ResetAction()),
tooltip: 'Reset',
child: Icon(Icons.delete),
);
}
returnFloatingActionButton(
/// The action is executed in the [ApplicationContext].
onPressed: () => context.dispatch<CounterState>(AddAction(1)),
tooltip: 'Increment',
child: Icon(Icons.add),
);
},
),
);
}
}
The state initialization at the root of the tree with the Fountain widget :
The application context maintains a unique global logical immutable state for the application.
The context also contains all the middlewares that will process the dispatched event.
The application context is provided to the widget tree from a Fountain so that any descendent widget can observe a property of the state with the select extension method. It can also dispatch events into the middlewares with the dispatch extension methods.
Middleware
The application middleware process the dispatched Events and can produce state updates.
They are composable by nature which means that each middleware can wrap another middleware.
Event
The events are inputs for middlewares. They can describe a user action, or a system event for exemple. They are processed by the middlewares which can produce new application states.
Included middlewares
To import middlewares, use the import 'package:fountain/middlewares.dart'; directive.
Actions
By default, the framework includes a ActionExecutor<TState> middleware that allows to define Action<TState>s which are then invoked directly to produce new states.
Defining an action
To create custom actions, inherits from Action<TState> and implement all of the update logic in the call method. Since the method returns a Stream, a convenient way to implement the logic is often by using async * generators which allows to yield a sequence of state updates.
Note that the actions aren't yielding states directly, but Updaters. This is to insist on the fact the the initial state may have changed during the action execution, and therefore, it must be taken into account when updated.
Logging
The framework also includes a Logging middleware that logs all events and state updates.
This middleware catches all unmanaged exceptions from middlewares below it and dispatches new events if so.
Fountain(
middlewares: <Middleware<CounterState>>[
ErrorHandler<CounterState>(
(context, event, initialState,error,stackTrace) {
// An unknow error occured during event processingreturnDisplayAlertAction('Sorry, an error occured');
},
),
...Fountain.defaultMiddlewares<CounterState>(),
],
// ...
);
About
Wait ... yet another state management solution for Flutter ?
Fountain is not so new to me, I've used this approach for a longtime now. Centralizing it as an opensource library makes a lot of sense to create a standard for a all of my personal and professional projects.
Inspired by
This project stands on the shoulders of giants, with the intention of reducing boilerplate, being minimalist and simple at its core.
Redux for the functional update cycle and general principles, with the purpose of having less boilerplate by being a bit more opiniated.
Express | Koa for their composability and modularity thanks to middlewares.
How is it different from other popular solutions ?
Provider : Fountain is more opiniated than Provider, and thus Provider is a more general purpose tool. Provider is often used in combination with a ChangeNotifier to create a simple state management solution.
Redux : Fountain has the same overall philosophy than Redux with Thunks but brings less boilerplate when dealing with asynchronous logic with ApplicationActions logic by using Streams. Fountain also brings the middleware concepts.
Bloc : Fountain use a global state instead of various Blocs. We believe it is important since there's a lot of areas which need to be aware of another part of your app logic. This makes also persistence, testability easier to deal with.