Bloc: access BlocProvider.of<Bloc>(context) in dispose method

Created on 19 Oct 2019  路  6Comments  路  Source: felangel/bloc

Hi, I'm having trouble trying to use BlocProvider.of(context) in the dispose method.

My code:

  @override
  void dispose() {
    final FiltersBloc filtersBloc = 
       BlocProvider.of<FiltersBloc>(context);
    super.dispose();
  }

error is:

flutter:         BlocProvider.of() called with a context that does not contain a Bloc of type FiltersBloc.
flutter:         No ancestor could be found starting from the context that was passed to
flutter: BlocProvider.of<FiltersBloc>().
flutter:
flutter:         This can happen if:
flutter:         1. The context you used comes from a widget above the BlocProvider.
flutter:         2. You used MultiBlocProvider and didn't explicity provide the BlocProvider types.
flutter:
flutter:         Good: BlocProvider<FiltersBloc>(builder: (context) => FiltersBloc())
flutter:         Bad: BlocProvider(builder: (context) => FiltersBloc()).
flutter:
flutter:         The context used was: FiltersDrawer(dirty, state: _FiltersDrawerState#86e8a)

Also, if I follow the error code and use final filtersBloc = BlocProvider<FiltersBloc>(builder: (context) => FiltersBloc()) I cannot call filtersBloc.dispatch() anymore.

I know for initState, we can just didChangeDependencies instead. But I cannot find an equivalent for dispose.

Any help would be greatly appreciated. Thanks!

question

Most helpful comment

No problem! Sorry for the delayed response but this seems like a Flutter limitation (https://github.com/flutter/flutter/pull/37961). Also, you can't access InheritedWidgets within dispose so you would probably need to lookup the bloc via BlocProvider in initState and add/dispatch an event to the same bloc instance (without doing a BlocProvider lookup) from dispose.

Hope that helps 馃憤

All 6 comments

Hi @theweiweiway 馃憢
Thanks for opening an issue!

Can you please provide a link to a sample app which illustrates the problem you鈥檙e having? Thanks!

Thanks for the quick reply as always Felix,

The problem is quite simple, so please let me try to explain this below. If it's not enough, I'll be happy to provide a link to a sample app

I have a scaffold and a drawer that slides in and out. I need to dispatch events when the drawer closes. The drawer can be closed by:

  1. clicking close
  2. sliding the drawer out

It's very easy to dispatch an event for case 1. However, for 2., I can only seem to be notified of when the drawer slides out via the dispose method. Please see code below:

class _MyHomePageState extends State<MyHomePage> {
  var _scaffoldKey = new GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
        builder: (context) => DrawerBloc(),
        child: Scaffold(
          key: _scaffoldKey,
          endDrawer: ClipRRect(
              borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(16),
                  bottomLeft: Radius.circular(16)),
              child: Drawer(child: MyDrawer())),
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(child: Text('hi')),
        ));
  }
}

class MyDrawer extends StatefulWidget {
  @override
  _MyDrawerState createState() => _MyDrawerState();
}

class _MyDrawerState extends State<MyDrawer> {
  @override
  void dispose() {
    final DrawerBloc drawerBloc = BlocProvider.of<DrawerBloc>(context);
    // dispatch event to bloc
    // this is required because the user can SLIDE THE DRAWER OUT
  }

  _close() {
    // I can easily dispatch event to bloc when the user taps this close button
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        FlatButton(onPressed: _close, child: Text('close')),
      ],
    );
  }
}

Please let me know if you would like to see sample code.

Thanks!

edit: sorry. didn't add the blocprovider

No problem! Sorry for the delayed response but this seems like a Flutter limitation (https://github.com/flutter/flutter/pull/37961). Also, you can't access InheritedWidgets within dispose so you would probably need to lookup the bloc via BlocProvider in initState and add/dispatch an event to the same bloc instance (without doing a BlocProvider lookup) from dispose.

Hope that helps 馃憤

Thank You! In case anyone else needs to do something like this, I did:

  FiltersBloc _filtersBloc;

  @override
  void dispose() {
      _filtersBloc.dispatch(EventHere());
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    final FiltersBloc filtersBloc = BlocProvider.of<FiltersBloc>(context);
    setState(() {
      _filtersBloc = filtersBloc;
    });
    super.didChangeDependencies();
  }

No problem! Also you don鈥檛 need setState and you can get the bloc in initState instead of didChangeDependencies 馃憤

ah, i see. OK, thanks!

Was this page helpful?
0 / 5 - 0 ratings