flutter_bloc subwidget closes the bloc of the parent widget

Issue

I am using the flutter_bloc package.

I have a page with a tabbar.
The page creates a bloc and provides it to the widgets, which are used as tab content.

class _MyScreenState extends State<MyScreen> {
  MyBloc _myBloc;
  ...

  Widget _buildTabBar() {
  ...

    var children = [
    _buildFirstTab()
    _buildSecondTab(),
    ];

    return WillPopScope(
      onWillPop: _onWillPop,
      child: DefaultTabController(
      length: children.length,
      child: Scaffold(
        appBar: PreferredSize(
            preferredSize: Size.fromHeight(75.0),
            child: AppBar(
              bottom: TabBar(isScrollable: true, tabs: tabs),
            )),
        body: TabBarView(
          children: children,
        ),
      ),
    ),
  );
  }
..
}

Widget _buildSecondTab() {
  if (_myBloc == null) {
    _myBloc = MyBloc(<..initialdata..>);
  }
  _myBloc.add(LoadServerDataEvent());

  return BlocProvider<MyBloc>(create: (_) => _myBloc, child: SecondTab());
}

The widget on the second tab gets the bloc from the BlocProvider and uses it.

class _SecondTabState extends State<SecondTab> {
  MyBloc _myBloc;

  @override
  void initState() {
    _myBloc = BlocProvider.of<MyBloc>(context);
    super.initState();
  }

My problem is that the block is automatically closed when I switch between the tabs.

This is kind of strange, because the block is still used on the page.

Solution

Well, you are doing a couple of things wrong:

  1. if you want your bloc to be accessible in both first and second tab you should wrap the whole tab bar with it,
  2. that’s very odd that you keep an instance of a bloc in _MyScreenState and do some magic with lazy init singeltone if (_myBloc == null) _myBloc = MyBloc(),
  3. The _myBloc.add(LoadServerDataEvent()); in most cases should be triggered in initState method of the _SecondTabState .
  4. That’s very unusal that a bloc gets initial data from the UI. If you want to build your architecture using blocs this initial data should come from another bloc.

But if you want to provide an existing bloc to the second tab and prevent it from being closed you should use:

BlocProvider.value(
  value: _myBloc,
  child: SecondTab(),
);

Instead:

BlocProvider<MyBloc>(create: (_) => _myBloc, child: SecondTab());

Answered By – Karol Lisiewicz

Answer Checked By – Willingham (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *