Siamak S
Siamak S

Reputation: 163

Flutter: Get Provider if exists otherwise return null instead of exception

When we use BlocProvider.of<OrderBloc>(context) to access Bloc object, it returns an exception if no OrderBloc exists on ancestor widgets of current context. Returned exceptions as follows:

No ancestor could be found starting from the context that was passed to BlocProvider.of<OrderBloc>().

But I want return null instead of exceptions when no OrderBloc exists on ancestor widgets. Consider following scenario:

var orderBloc = BlocProvider.of<OrderBloc>(context);

return Container(child: orderBloc == null
      ? Text('-')
      : BlocBuilder<OrderBloc, OrderState>(
          bloc: orderBloc,
          builder: (context, state) {
            // build something if orderBloc exists.
          },

        ),          
);

Upvotes: 6

Views: 1856

Answers (2)

Snow Albert
Snow Albert

Reputation: 577

  1. find the widget that hold the view model.
    • to make sure there no exception when use BlocProvider.of.
  2. if widget exist then to find view model else return null.
  static YouViewModel getViewModel(
      BuildContext context) {
    bool isFromSpecifyWidget = false;

    context.visitAncestorElements((element) {
      isFromSpecifyWidget = element.widget is YouWidget;
      return !isFromSpecifyWidget;
    });

    if (isFromSpecifyWidget) {
      return BlocProvider.of<YouViewModel>(context, listen: false);
    }

    return null;
  }

Not perfect solution, because you must specify the widget.

Upvotes: 0

Luis A. Chaglla
Luis A. Chaglla

Reputation: 600

You could wrap that line with try/catch like this:

var orderBloc;
try {
  orderBloc = BlocProvider.of<OrderBloc>(context);
} catch (e) {}

return Container(child: orderBloc == null
  ? Text('-')
  : BlocBuilder<OrderBloc, OrderState>(
      bloc: orderBloc,
      builder: (context, state) {
        // build something if orderBloc exists.
      },
    ),          
);

EDIT:

If you want to reduce the boilerplate:

extension ReadOrNull on BuildContext {
  T? readOrNull<T>() {
    try {
      return read<T>();
    } on ProviderNotFoundException catch (_) {
      return null;
    }
  }
}

Then your code will be:

var orderBloc = context.readOrNull<OrderBloc>();

return Container(child: orderBloc == null
  ? Text('-')
  : BlocBuilder<OrderBloc, OrderState>(
      bloc: orderBloc,
      builder: (context, state) {
        // build something if orderBloc exists.
      },
    ),          
);

Upvotes: 8

Related Questions