Flutter Bloc/State delayed activities when moving between pages
michelhabib opened this issue ยท 5 comments
This might be more of a question, I looked everywhere, and now I think it is better to ask a direct question. Not sure if this is the right place. I am using Flutter Bloc package.
I am expecting that as soon as I navigate from page A to page B, and remove all other pages in stack if any (PushAndRemoveUntil false), then:
- All defined blocs inside Page A shall be closed immediately (unless defined above MaterialApp),
- And BlocBuilders/BlocListeners of Page A should stop accepting any new states, Especially if I cancel stream subscriptions defined in the bloc.
However,
- The bloc close function is delayed, which also delays stream subscription cancellation defined in the close function,
- the bloc close function may not run until the build function of Page B runs (sometimes Built twice)
- And BlocBuilder/BlocListener may still run on the Page A (not sure how!) and may disturb my app's behavior.
Questions:
- Should I add more logic to the BlocListener of Page A to stop accepting new states when it calls Navigator?
- Should I add more logic to the BlocBuilder, to stop rebuilding Page A widgets in the background, while it is waiting to be destroyed (I mean both the widget and the BlocBuilder)
- Should I call the Bloc Close function earlier manually?
I have been trying to look for solutions, but they all go to a direction where I add management to state management, which is what takes me back to the source, here.
I know I haven't submitted any source code, because the issue appears with larger and complex behavior, too difficult to extract in an example. I could try to put something together, if you feel this is not the expected behavior.
Hi @michelhabib ๐
Thanks for opening an issue!
Can you provide a reproduction sample? As long as the bloc was created by a BlocProvider you shouldn't need to manually call close
. The bloc instance should be closed as soon as the associated BlocProvider
instance is unmounted from the widget tree.
Closing for now since there isn't a reproduction sample.
Hi, @felangel
This issue occurs to me, too.
I provide the sample code below. I want to know the reason for BlocBase.close
.
code:
- PageA.dart
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (_) => BlocProvider<TestCubit>.value(
value: BlocProvider.of<TestCubit>(context),
child: PageB(),
)),
(route) => false,
);
- PageB.dart
class PageB extends StatefulWidget {
@override
State<StatefulWidget> createState() => _PageBState();
}
class _PageBState extends State<PageB> {
late TestCubit _testCubit;
@override
void initState() {
super.initState();
_testCubit = context.read<TestCubit>();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: BlocBuilder<TestCubit, TestState>(
builder: (context, state) {
return Wrap(
runSpacing: 15,
children: [
Text(
"์ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.",
),
],
);
}),
);
}
}
Hi, @felangel
This issue occurs to me, too.
I provide the sample code below. I want to know the reason forBlocBase.close
.code:
- PageA.dart
Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute( builder: (_) => BlocProvider<TestCubit>.value( value: BlocProvider.of<TestCubit>(context), child: PageB(), )), (route) => false, );
- PageB.dart
class PageB extends StatefulWidget { @override State<StatefulWidget> createState() => _PageBState(); } class _PageBState extends State<PageB> { late TestCubit _testCubit; @override void initState() { super.initState(); _testCubit = context.read<TestCubit>(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: BlocBuilder<TestCubit, TestState>( builder: (context, state) { return Wrap( runSpacing: 15, children: [ Text( "์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ฃผ์ธ์.", ), ], ); }), ); } }
Can you provide a link to a complete minimal reproduction sample?
Hi, @felangel
This issue occurs to me, too.
I provide the sample code below. I want to know the reason forBlocBase.close
.
code:
- PageA.dart
Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute( builder: (_) => BlocProvider<TestCubit>.value( value: BlocProvider.of<TestCubit>(context), child: PageB(), )), (route) => false, );
- PageB.dart
class PageB extends StatefulWidget { @override State<StatefulWidget> createState() => _PageBState(); } class _PageBState extends State<PageB> { late TestCubit _testCubit; @override void initState() { super.initState(); _testCubit = context.read<TestCubit>(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: BlocBuilder<TestCubit, TestState>( builder: (context, state) { return Wrap( runSpacing: 15, children: [ Text( "์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ฃผ์ธ์.", ), ], ); }), ); } }
Can you provide a link to a complete minimal reproduction sample?
I'm sorry, I understood this issue the other way around.
I think it should be mounted.
When BlocProvider instance receive as BlocProvider.value
, the BlocProvider instance was not unmounted in the widget tree.
Please check the code.
[project infomation]
- main -> PageA (provide TestCubit)
- PageA -> PageB (BlocProvide.value)
- change TestState using TextField
sample code :
https://github.com/doitduri/bloc_sample