felangel/bloc

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:

  1. PageA.dart
Navigator.of(context).pushAndRemoveUntil(
  MaterialPageRoute(
      builder: (_) => BlocProvider<TestCubit>.value(
            value: BlocProvider.of<TestCubit>(context),
            child: PageB(),
          )),
  (route) => false,
);
  1. 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(
                    "์ƒˆ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.",
                  ),
                ],
              );
            }),
    );
  }
}

image

Hi, @felangel

This issue occurs to me, too.
I provide the sample code below. I want to know the reason for BlocBase.close.

code:

  1. PageA.dart
Navigator.of(context).pushAndRemoveUntil(
  MaterialPageRoute(
      builder: (_) => BlocProvider<TestCubit>.value(
            value: BlocProvider.of<TestCubit>(context),
            child: PageB(),
          )),
  (route) => false,
);
  1. 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(
                    "์ƒˆ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.",
                  ),
                ],
              );
            }),
    );
  }
}

image

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 for BlocBase.close.
code:

  1. PageA.dart
Navigator.of(context).pushAndRemoveUntil(
  MaterialPageRoute(
      builder: (_) => BlocProvider<TestCubit>.value(
            value: BlocProvider.of<TestCubit>(context),
            child: PageB(),
          )),
  (route) => false,
);
  1. 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(
                    "์ƒˆ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.",
                  ),
                ],
              );
            }),
    );
  }
}

image

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]

  1. main -> PageA (provide TestCubit)
  2. PageA -> PageB (BlocProvide.value)
  • change TestState using TextField

sample project demo :
bloc

sample code :
https://github.com/doitduri/bloc_sample