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

2

6

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.
          },

        ),          
);
Retiring answered 30/4, 2021 at 11:2 Comment(0)
H
8

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.
      },
    ),          
);
Harrell answered 30/4, 2021 at 11:38 Comment(1)
I think it should be a more straight way instead of exception handling. I think it could be a common scenario to check a Provider exists or not.Retiring
I
0
  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.

Illtimed answered 7/9, 2022 at 10:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.