Bloc: I'm having trouble defining base MultiBlocProvider

Created on 4 Mar 2020  路  4Comments  路  Source: felangel/bloc

I'm trying to define a BaseMultiBlocProvider class which gives me more control to invoke bloc on widget init & rebuild and helps reduce boilerplate code. But doing this compiler keeps complaining about BlocProvider.of() called with a context that does not contain a Bloc of type ... down on the widget tree.

import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class BaseMultiBlocView extends StatefulWidget {
  const BaseMultiBlocView({
    Key key,
    @required this.items,
    this.child,
  })  : assert(items != null),
        super(key: key);

  final List<MultiBlocViewItem> items;
  final Widget child;

  @override
  _BaseMultiBlocViewState createState() => _BaseMultiBlocViewState();
}

class _BaseMultiBlocViewState extends State<BaseMultiBlocView> {
  @override
  void initState() {
    super.initState();
    widget.items.map((item) {
      if (item.onBlocReady != null && !item.isExisting) {
        item.onBlocReady(item.bloc);
      }
    });
  }

  @override
  void didUpdateWidget(BaseMultiBlocView oldWidget) {
    super.didUpdateWidget(oldWidget);
    widget.items.map((item) {
      if (item.onRebuild != null) {
        item.onRebuild(item.bloc);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: widget.items
          .map(
            (item) => item.isExisting
                ? BlocProvider.value(
                    value: item.bloc,
                  )
                : BlocProvider(
                    create: (_) => item.bloc,
                  ),
          )
          .toList(growable: false),
      child: widget.child,
    );
  }
}

class MultiBlocViewItem<T extends Bloc<dynamic, dynamic>> {
  const MultiBlocViewItem({
    @required this.bloc,
    this.onBlocReady,
    this.onRebuild,
    this.isExisting = false,
  }) : assert(bloc != null);

  final bool isExisting;
  final T bloc;
  final void Function(T) onBlocReady;
  final void Function(T) onRebuild;
}

Can you help me clarify what did I do wrong about the code?

question

Most helpful comment

I'm clear now, thank you so much @felangel.

All 4 comments

Hi @dungnv2602 馃憢
Thanks for opening an issue!

The problem is you鈥檙e mapping a List which has a dynamic bloc. If you look at the type of BlocProvider when you call create it will likely be BlocProvider> which means if you try to lookup the bloc later by type it will fail.

This is the same reason why MultiBlocProvider takes a List<BlocProvider> and not a List<Bloc>.

Can you describe why you need this widget and what problem you鈥檙e trying to solve? Thanks and hope that helps 馃憤

My problem is I want more fine control over when bloc invokes event. As you can see from my code above, what I'm trying to do is invoking bloc only in initState. Because if I don't do that, normally in situations which I want to invoke bloc on create, I will implement bloc and then use cascade like this.

MultiBlocProvider(
            providers: [
              BlocProvider(
                create: (_) => TmdbBloc<MovieAccountStatus>(locator<TmdbRepo>())
                  ..add( // cascade 
                    BlocLoad(...),
                    ),
                  ),
              ),
              BlocProvider(
                create: (_) =>
                    TmdbBloc<List<UserListItemStatus>>(locator<TmdbRepo>())
                      ..add(  // cascade 
                        BlocLoad(...),
                      ),
              ),
            ],
),

I feel this approach is somewhat wrong as I scare whether or not it will reinvoke when widget rebuild or maybe this is not a good practice.
Can you help me clarify this?

@dungnv2602 create will only be called once so I would recommend using the cascade approach rather than the custom MultiBlocView.

I'm clear now, thank you so much @felangel.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shawnchan2014 picture shawnchan2014  路  3Comments

frankrod picture frankrod  路  3Comments

1AlexFix1 picture 1AlexFix1  路  3Comments

clicksocial picture clicksocial  路  3Comments

rsnider19 picture rsnider19  路  3Comments