So, I have a project in flutter and I'm trying to build a list of Cards where the contents depends on my OrderModel class and I'm trying to use Provider to achieve this, but I get this error:
════════ Exception caught by scheduler library ══════════════════════════
Tried to listen to a value exposed with provider, from outside of the widget tree.
This is likely caused by an event handler (like a button's onPressed) that called
Provider.of without passing listen: false
.
To fix, write: Provider.of(context, listen: false);
It is unsupported because may pointlessly rebuild the widget associated to the event handler, when the widget tree doesn't care about the value. 'package:provider/src/provider.dart': Failed assertion: line 193 pos 7: 'context.owner.debugBuilding || listen == false || _debugIsInInheritedProviderUpdate'
When the exception was thrown, this was the stack
#2 Provider.of package:provider/src/provider.dart:193
#3 _OrderHistoryState._onAfterBuild package:shinier_store/screens/order_history.dart:60
#4 _OrderHistoryState.build. package:shinier_store/screens/order_history.dart:67
#5 SchedulerBinding._invokeFrameCallback package:flutter/…/scheduler/binding.dart:1102
#6 SchedulerBinding.handleDrawFrame package:flutter/…/scheduler/binding.dart:1049 ...
═════════════════════════════════════════════════════════ Stacktrace for the Provider call at _onAfterBuild()
I/flutter ( 3092): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:42:39)
I/flutter ( 3092): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:38:5)
I/flutter ( 3092): #2 Provider.of package:provider/src/provider.dart:193
I/flutter ( 3092): #3 _OrderHistoryState._onAfterBuild package:shinier_store/screens/order_history.dart:61
I/flutter ( 3092): #4 _OrderHistoryState.build.<anonymous closure>
package:shinier_store/screens/order_history.dart:71
I/flutter ( 3092): #5 SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1102
I/flutter ( 3092): #6 SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1049
I/flutter ( 3092): #7 SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:957
I/flutter ( 3092): #8 _rootRun (dart:async/zone.dart:1126:13)
I/flutter ( 3092): #9 _CustomZone.run (dart:async/zone.dart:1023:19)
I/flutter ( 3092): #10 _CustomZone.runGuarded (dart:async/zone.dart:925:7)
I/flutter ( 3092): #11 _invoke (dart:ui/hooks.dart:259:10)
I/flutter ( 3092): #12 _drawFrame (dart:ui/hooks.dart:217:3)
I don't know how can I possibly solve it since I added the listen:false to my Provider call. I tried using WidgetBinding, cause I thought the Provider call should be made after build is done but that didn't seem to solve the problem.
Here are the codes:
OrderModel class
class OrderModel extends ChangeNotifier {
List<Order> myOrders;
bool isLoading = true;
String errMsg;
int page = 1;
bool endPage = false;
void getMyOrder({UserModel userModel}) async {
try {
isLoading = true;
notifyListeners();
myOrders = await WooCommerce().getMyOrders(userModel: userModel, page: 1);
page = 1;
errMsg = null;
isLoading = false;
endPage = false;
notifyListeners();
} catch (err) {
errMsg =
"There is an issue with the app during request the data, please contact admin for fixing the issues " +
err.toString();
isLoading = false;
notifyListeners();
}
}
void loadMore({UserModel userModel}) async {
try {
isLoading = true;
page = page + 1;
notifyListeners();
var orders =
await WooCommerce().getMyOrders(userModel: userModel, page: page);
myOrders = [...myOrders, ...orders];
if (orders.length == 0) endPage = true;
errMsg = null;
isLoading = false;
notifyListeners();
} catch (err) {
errMsg =
"There is an issue with the app during request the data, please contact admin for fixing the issues " +
err.toString();
isLoading = false;
notifyListeners();
}
}
}
order_history.dart - state class
class _OrderHistoryState extends State<OrderHistory> {
void _onAfterBuild(BuildContext context){
Provider.of<OrderModel>(context, listen: false)
.getMyOrder(userModel: Provider.of<UserModel>(context));
}
@override
Widget build(BuildContext context) {
var formatter = DateFormat('dd-MM-yyyy');
var model = Provider.of<OrderModel>(context);
WidgetsBinding.instance.addPostFrameCallback((_) => _onAfterBuild(context));
return Scaffold(
appBar: AppBar(
title: Text(
'Order History',
style: TextStyle(fontWeight: FontWeight.bold),
),
elevation: 0.0),
body: model.myOrders == null ? Center() :
Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.separated(
separatorBuilder: (_, __) => SizedBox(height: 10.0),
itemCount: model.myOrders.length,
itemBuilder: (context, index) {
String stat = model.myOrders[index].status;
return Card(
color: _buildColor(stat),
elevation: 3.5,
...
}
}
main.dart - build method
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserModel()),
ChangeNotifierProvider(create: (_) => CartModel()),
ChangeNotifierProvider(create: (_) => SearchModel()),
ChangeNotifierProvider(create: (_) => OrderModel()),
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Colors.white,
backgroundColor: Colors.white,
canvasColor: Colors.white,
),
home: MainTabs(),
debugShowCheckedModeBanner: false,
localizationsDelegates: [
i18n,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: i18n.supportedLocales,
),
);
}
I too got similar error and found out that in the newer version of Provider Package (I am using provider: ^6.0.1
) you have to pass listen: false
whereever you are updating the provider data.
For example on a Tap of button or any Widgets onChanged Event. Below is an example with TextField onChanged callback.
TextField(
onChanged: (newText) {
Provider.of<Data>(context, listen: false).changeString(newText);
},
);
The error seems to point out to these two lines of code to be causing the issue.
#3 _OrderHistoryState._onAfterBuild package:shinier_store/screens/order_history.dart:60
#4 _OrderHistoryState.build. package:shinier_store/screens/order_history.dart:67
The repro you've provided is incomplete and I can only guess the required flag listen: false
has been added on _onAfterBuild()
. However, the error logs points that var model = Provider.of<OrderModel>(context);
inside Widget build()
needs to also have the flag. The reason for this flag requirement is explained in the docs.
If you're still having issues, a working minimal repro will be helpful for us to understand why this behavior occurs.
If you use provider version ^6.0.2, use:
context.read<TaskData>().addMyTask(
Task(
name: newTaskTitle,
),
);
Instead of this:
context.watch<TaskData>().addMyTask(
Task(
name: newTaskTitle,
),
);
If you are using provider ^6.0.2
then use:
context.read<YourFunction>()
not:
context.watch<YourFunction>()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With