skip to Main Content

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,
      ),
    );
  }

5

Answers


  1. 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.

    Login or Signup to reply.
  2. I also found out that use of BlocProvider, even without the listen parameter seems to solve this. But in this case you would be using BLOC for your state management.

    In all cases that I use var yyystate = BlocProvider.of(context); I always add the listen parameter.

    Login or Signup to reply.
  3. 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);
      },
    );
    
    Login or Signup to reply.
  4. 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,
              ),
            );
    
    Login or Signup to reply.
  5. If you are using provider ^6.0.2 then use:

    context.read<YourFunction>()
    

    not:

    context.watch<YourFunction>()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search