Hello, I have looked at a few articles that you have posted here. I’m just a hobbyist, didn’t really went past provider, have tried riverpod for a small app.
I only made this, most of it before AI agents were widely available, it has a few users GitHub - mihalycsaba/snag: Client application for steamgifts.com · GitHub
I want to add something more “serious” for some improvements I want to make in the app, don’t know yet if it’s necessary. If it makes the app more efficient that’s a good enough reason too.
Is there a simple guide for switching to bloc_signals from provider? Or can you give some advice based on the app I have made?
The simplest way is to install the RandalSchwartz/BlocSignal skill into your agent, and say “convert this to BlocSignal”.
However, if you’re doing it by hand, the mental model maps very cleanly:
1. State Container
ChangeNotifierbecomesCubitSignal<StateType>.- Instead of mutating properties and calling
notifyListeners(), you callemit(newState). - Updates propagate synchronously in the same frame and are automatically de-duplicated (
==), so widgets never re-render if the state hasn’t actually changed.
// Before: Provider (ChangeNotifier)
class GiveawayNotifier extends ChangeNotifier {
List<Giveaway> items = [];
void update(List<Giveaway> newItems) {
items = newItems;
notifyListeners();
}
}
// After: BlocSignal (CubitSignal)
class GiveawayCubit extends CubitSignal<List<Giveaway>> {
GiveawayCubit() : super(initialState: const []);
void update(List<Giveaway> newItems) => emit(newItems);
}
2. Dependency Injection
ChangeNotifierProvider(create: (_) => ...)becomesBlocSignalProvider(create: (_) => ...).MultiProviderbecomesMultiBlocSignalProvider.
3. Consuming in the Widget Tree
- Triggering actions:
context.read<MyNotifier>()stayscontext.read<MyCubit>()(it does not subscribe to rebuilds). - Rebuilding UI:
ConsumerbecomesBlocSignalBuilder<MyCubit, MyState>. - Fine-grained properties:
Selector<Notifier, Value>becomescontext.select<MyCubit, Value>((state) => state.someValue). - Side-effects (Dialogs, SnackBars, Navigation): Use
BlocSignalListenerorBlocSignalConsumer(which combines listener and builder).
4. Why it pays off in efficiency for an app like Snag
- Eliminate over-rebuilding: In
ChangeNotifier, callingnotifyListeners()often causes broad rebuilds across large subtrees.BlocSignalonly rebuilds when the emitted state actually differs. - Effortless derived state: If your app filters giveaways, computes points, or tracks active entries, you can define
late finalcomputed()signals directly in your Cubit. They compute lazily and cache their values automatically until the underlying state changes.