popsicle 0.0.2-alpha
popsicle: ^0.0.2-alpha copied to clipboard
Popsicle is a lightweight, reactive state management and DI framework for Flutter. Built on the philosophy f(state) = UI, it simplifies building scalable, declarative apps.
๐ก Popsicle โ Simple. Reactive. Composable #
Popsicle
is a lightweight, extensible state management and dependency injection (DI) framework for Flutter, built with simplicity and power in mind. Designed for developers who want full control without boilerplate,Popsicle
unifies state, DI, and lifecycle management under one clean architecture.
๐ Features #
- โ
Reactive & composable state management (
ReactiveState
,AsyncState
,StreamState
) - โ Built-in dependency injection without global variables
- โ
Zero-boilerplate DI with centralized configuration via
AppDI
class - โ Lifecycle-aware state observers & disposal
- โ Middleware support for state transformation or interception
- โ Supports Flutter & Dart CLI applications
- โ Designed for both small and large-scale apps
- โ Modular architecture for easy extensibility
๐ฆ Installation #
Add popsicle
to your pubspec.yaml
:
dependencies:
popsicle: ^1.0.0
Then run:
flutter pub get
๐ง Philosophy #
Popsicle is inspired by the idea of:
f(State) => UI
We believe the UI should be a pure function of state โ with your logic encapsulated, testable, and clean.
๐ ๏ธ Getting Started #
1. Extend AppDI
to register dependencies #
class AppDI extends DIConfigurator {
static final authService = container.reg<AuthService>(AuthServiceImpl());
static final logger = container.regLazy(() => Logger());
}
2. Inject Popsicle in your app root (Optional ๐) #
void main() {
runApp(
PopsicleDI(
app: const MyApp(),
inject: () => AppDI(),
),
);
}
3. Use anywhere (without context!) #
final auth = Popsicle.instance<AuthService>();
auth.login();
4. Create a reactive state #
final counter = ReactiveState<int>(0);
counter.listen((value) {
print("Counter updated: $value");
});
counter.value++; // Counter updated: 1
๐ฏ Lifecycle Management #
Popsicle supports lifecycle-aware widgets and cleanup:
class MyState extends ReactiveState<int> with Disposable {
MyState() {
startTimer();
}
void startTimer() {
Timer.periodic(Duration(seconds: 1), (_) => value++);
}
@override
void dispose() {
print("Cleaning up MyState");
super.dispose();
}
}
๐งช Testing #
final testContainer = DIContainer();
testContainer.registerSingleton<MockService>(MockService());
final service = testContainer.resolve<MockService>();
expect(service.doSomething(), true);
๐งฉ Extensions (Planned) #
- โ Code generation for injectable services
- โ Integration with Riverpod, Bloc
- โ Dev tools inspector panel
- โ Web dashboard for live state inspection
๐ API Overview #
Feature | Class/Method | Description |
---|---|---|
DI Registration | container.registerSingleton<T>() |
Register a singleton instance |
Lazy Singleton | container.registerFactory() |
Register a lazy-loaded singleton |
Reactive State | ReactiveState<T> |
State that emits changes |
Async State | AsyncState<T> |
Handle async loading / error / data |
Stream State | StreamState<T> |
Wrap a Dart stream as state |
Global Access | Popsicle.instance<T>() |
Access service globally, no context needed |
๐ก Why Popsicle? #
- No black-box magic
- Minimal boilerplate
- Pure Dart core
- Flutter-ready but framework-agnostic
- Clean architecture friendly
๐ฅ Community #
Coming soon: Discord + GitHub Discussions
๐ชช License #
Apache License 2.0 ยฉ AR Rahman
This project is licensed under the Apache License 2.0.
๐ฌ Feedback #
Have ideas or suggestions? Feel free to open an issue or pull request!