Reputation: 163
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
Reputation: 577
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
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