NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #5717 most downloaded on pub.dev
ASP (Atomic State Pattern) offers a simplified, Predictable and Powerful State Management for Flutter.
Last release 2 years ago
no release in 18 months
Ships unpredictably
gaps range from 8 days to 11 months
Most releases are documented
notes for 10 of 14 stable releases
Nothing withdrawn
no release was ever pulled
3 years old
14 releases · first in 2023
One column per quarter.
- Fix: Distict param
Full Changelog : v2.0.1...v2.0.2
Full Changelog: v2.0.1...v2.0.2
Full Changelog : v2.0.0...v2.0.1
Full Changelog: v2.0.0...v2.0.1
Full Changelog : Read this post
Full Changelog: Read this post
After extensive feedback, we are changing the API to make the standard more intuitive and user-friendly. We also added stricter limits for more complex projects and introduced a “predictability” system in state changes to improve tracking and debugging while reducing unwanted side effects. Some changes may seem drastic, but we believe everything will make more sense once you give this new API a chance.
Let’s start with what has been removed, followed by the new features:
final productsState = atom<List<Product>>([]);
[BREAKING CHANGE]: Due to the new API capabilities, some widgets have changed. ASP now adopts hook_state for state distribution, retiring RxRoot, which has been removed. We will discuss the new state distribution method based on hooks later. RxCallback has also been removed for the same reason. The RxBuilder has been renamed to AtomBuilder for semantic clarity.
[BREAKING CHANGE]: The Reducer API in ASP was a major source of confusion and complaints. While it was magical and capable of deriving values from multiple Atoms, the reactive actions system needed a rethink to make the process more predictable and easier to learn. The steep learning curve of RxReducer led us to segregate it into two new APIs: AtomAction and AtomSelector. As a result, RxReducer no longer exists. However, don’t worry—something much better is coming.
[BREAKING CHANGE]: ASP is moving towards a more functional approach, emphasizing functions over classes. Some components, such as Atom, have been converted to functions. The main difference you’ll notice is the change in the capitalization of the component name:
//v1
final counter = Atom(0);
//v2
final counter = atom(0);
void main() {
AtomObserver.changes((status) {
print(status.atom); // counterState
print(status.action); // incrementAction
print(status.event.name) // change
});
runApp(MyApp());
}
The Atom is the heart of atomic state. It allows creating an object that stores an autonomous micro-state, observable by anything—be it a widget or a function. However, an Atom could also be modified by anything, anywhere, leading to classic side-effect problems. To address this, we removed the state setter and added a new component called AtomAction. This way, while an Atom can still be listened to by anything, it can only be modified in a specific place, enhancing predictability and reducing uncontrolled side effects.
Example:
// atom creation
final counterState = atom(0);
// listen changes
counterState.addListener((){
print(counterState.state); // 1
});
// action creation
final increment = atomAction((set){
return set(counterState, 1);
});
// execute action
increment()
Actions can also accept up to 3 arguments and be used as a pub-sub mechanism:
final counterAction = atomAction1<String>((set, action){
final state = counterState.state;
if(action == 'INCREMENT'){
set(counterState, state + 1);
} else if(action == 'DECREMENT'){
set(counterState, state - 1);
}
});
The atomAction feature opens up numerous possibilities, functioning as both a simple action and a complex reducer. We replaced RxReducer with AtomAction for action calls. To fully replace RxReducer, we also needed a way to handle the derivation of multiple Atoms, which we achieve using the AtomSelector API.
[NEW]: Data derivation with AtomSelector.<br> Managing state distribution and converging multiple states into a new one was identified as the major challenge in the case study that led to the creation of ASP. We introduced a very simple way to combine multiple Atoms and compute a new value whenever any of them changes. This is very straightforward with AtomSelector:
// atoms
final nameState = atom('');
final lastNameState = atom('');
// selectors
final fullName = selector((get){
final name = get(nameState);
final lastName = get(lastNameState);
return '$name $lastName';
});
// actions
final changeName = atomAction1<String>((set, name){
set(nameState, name);
});
changeName('Matias');
Within the selector’s internal scope, the get property is used to subscribe to an Atom. This visual indicator shows what is being observed. The example above demonstrates the three pillars of ASP: Atoms, Selectors, and Actions.
There is also a way to derive states asynchronously with AsyncSelector:
final userIdState = atom(1);
final userState = asyncSelector<User>(
User.empty(),
(get) async {
final id = get(userIdState);
final response = await dio.get('/user/$id');
return User.fromJson(response.data);
}
);
This example shows a more complex derivation where modifying an Atom triggers an external API call. Despite this complexity, RxReducer users should find it familiar. It’s worth noting that any Selector is also an Atom and shares the same internal APIs. Now that we’ve shown how to use Atom with Selector and modify it only in Actions, let’s talk about how we’ve made it easier to connect all this with Widgets.
final disposer = atomEffect(
(get) => get(counterState),
(state) => print('Number is $state'),
);
// release
disposer();
The atomEffect might not be used as often, as there is a hook that does the same thing and automatically manages the lifecycle, including automatic disposal.
We have two hooks: 1. useAtomState: Subscribes to the Atom and rebuilds the Widget when the state changes. 2. useAtomEffect: Subscribes to one or more Atoms and triggers a callback when they change. This does not affect the Widget’s state. It is great for executing code like Snackbar or Navigator.
With useAtomEffect, RxCallback is no longer necessary and has been removed. Pay attention to the mixin that enables Hooks:<br>
For StatelessWidget, add the HookMixin mixin.<br> For StatefulWidget, add the HookStateMixin mixin to the State.<br>
Hooks will only be available after adding the mixin correctly.
Example:
class CounterPage extends StatelessWidget with HookMixin {
const CounterPage({super.key});
void callSnackBar(int state){
if(state > 5){
final snackBar = SnackBar(content: Text('Max $state'));
Asuka.showSnackBar(snackBar);
}
}
@override
Widget build(BuildContext context) {
//listen atom
final state = useAtomState(counterState);
// listen and call function
useAtomEffect(
(get) => get(counterState),
effect: callSnackBar,
);
...
Hooks manage the lifecycle automatically, so there is no need to worry about memory "releases" like "dispose". A dream come true!
OTHER CHANGES
[BREAKING CHANGE]: Atom.value is now Atom.state.
[NEW]: The distinct property has been added to Atom to specify if the user wants to trigger reactivity even if the same state is received.
[NEW]: A new documentation available at https://asp.flutterando.com.br.
[FIX]: Corrected all usage examples.
All support is free in Brazil's largest Flutter community, Flutterando. Join us on Discord.
Let's set the pattern together!
Nothing published for this version
docs update example readme by @dtodt in #3
Full Changelog: https://github.com/Flutterando/asp/commits/v1.2.0
Atom.next and Atom.buffer;Added: Pipers: Distinct and multiPipe;
* Added: Pipes; * Added: AtomObserver;
* Fix callback error;
* Added automatic track * fix reactive callback
Nothing published for this version
Nothing published for this version
Nothing published for this version
* Release!
Your coding agent can read these notes before it upgrades. Set up the MCP server →