-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
Describe the bug
When injecting a cubit with BlocProvider.value and then building with BlocBuilder, changing the cubit to a new instance does not cause the BlocBuilder to subscribe to state changes in the new cubit.
To Reproduce
My desired use case is to replace the bloc instance in the context when some input changes, automatically closing the old instance:
/// A widget that acts identically to [BlocProvider] except it will close its
/// cubit and recreate it when [input] changes.
class BlocInputProvider<C extends Cubit, Input> extends StatefulWidget {
final Input input;
final C Function(BuildContext, Input) create;
final Widget child;
BlocInputProvider({
Key key,
@required this.input,
@required this.create,
@required this.child,
}) : assert(child != null);
@override
_BlocInputProviderState<C, Input> createState() =>
_BlocInputProviderState<C, Input>();
}
class _BlocInputProviderState<C extends Cubit, Input>
extends State<BlocInputProvider<C, Input>> {
C _cubit;
@override
void initState() {
super.initState();
_createCubit();
}
@override
void dispose() {
super.dispose();
_cubit.close();
}
@override
void didUpdateWidget(covariant BlocInputProvider<C, Input> oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.input != oldWidget.input) {
_cubit.close();
_createCubit();
}
}
@override
Widget build(BuildContext context) {
return BlocProvider<C>.value(
value: _cubit,
child: widget.child,
);
}
void _createCubit() {
_cubit = widget.create(context, widget.input);
}
}
However, BlocBuilder in the subtree doesn't react to the cubit being replaced. Digging into BlocBuilderBase, it looks like it only checks for a new instance of the bloc in didUpdateWidget using context.read, meaning it won't know about the new cubit instance until its configuration changes.
I'm reporting this as a bug, but it's very possible this is the intended behavior and there's a very good reason for it!