简体   繁体   English

试图从小部件树外部监听提供者公开的值

[英]Tried to listen to a value exposed with provider, from outside of the widget tree

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:所以,我有一个颤动的项目,我正在尝试构建一个卡片列表,其中的内容取决于我的 OrderModel 类,我正在尝试使用 Provider 来实现这一点,但我收到了这个错误:

════════ 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 .这可能是由调用 Provider.of 而不传递listen: false的事件处理程序(如按钮的 onPressed)引起的。

To fix, write: Provider.of(context, listen: false);要修复,请编写: 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 || 'package:provider/src/provider.dart':断言失败:第 193 行 pos 7:'context.owner.debugBuilding || listen == false ||听 == 假 || _debugIsInInheritedProviderUpdate' _debugIsInInheritedProviderUpdate'

When the exception was thrown, this was the stack抛出异常时,这是堆栈

#2 Provider.of package:provider/src/provider.dart:193 #2 Provider.of 包:provider/src/provider.dart:193

#3 _OrderHistoryState._onAfterBuild package:shinier_store/screens/order_history.dart:60 #3 _OrderHistoryState._onAfterBuild 包:shinier_store/screens/order_history.dart:60

#4 _OrderHistoryState.build. #4 _OrderHistoryState.build。 package:shinier_store/screens/order_history.dart:67包:shinier_store/screens/order_history.dart:67

#5 SchedulerBinding._invokeFrameCallback package:flutter/…/scheduler/binding.dart:1102 #5 SchedulerBinding._invokeFrameCallback package:flutter/…/scheduler/binding.dart:1102

#6 SchedulerBinding.handleDrawFrame package:flutter/…/scheduler/binding.dart:1049 ... #6 SchedulerBinding.handleDrawFrame 包:flutter/.../scheduler/binding.dart:1049 ...

═════════════════════════════════════════════════════════ Stacktrace for the Provider call at _onAfterBuild() ══════════════════════════════════════════════════ ═══════ _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.我不知道如何解决它,因为我将 listen:false 添加到我的 Provider 调用中。 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.我尝试使用 WidgetBinding,因为我认为应该在构建完成后进行 Provider 调用,但这似乎并没有解决问题。

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 order_history.dart - 状态类

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 main.dart - 构建方法

  @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.我也遇到了类似的错误,并发现在更新版本的 Provider Package 中(我正在使用provider: ^6.0.1 )你必须通过listen: false来更新提供者数据。

For example on a Tap of button or any Widgets onChanged Event.例如,点击按钮或任何小部件 onChanged 事件。 Below is an example with TextField onChanged callback.下面是一个带有 TextField onChanged 回调的示例。

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() .您提供的复制不完整,我只能猜测所需的标志listen: false已添加到_onAfterBuild() However, the error logs points that var model = Provider.of<OrderModel>(context);但是,错误日志指出var model = Provider.of<OrderModel>(context); inside Widget build() needs to also have the flag.Widget build()内部也需要有标志。 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:如果您使用提供程序版本 ^6.0.2,请使用:

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:如果您使用的是提供程序^6.0.2 ,请使用:

context.read<YourFunction>()

not:不是:

context.watch<YourFunction>()

I also found out that use of BlocProvider, even without the listen parameter seems to solve this.我还发现使用 BlocProvider,即使没有 listen 参数似乎也可以解决这个问题。 But in this case you would be using BLOC for your state management.但在这种情况下,您将使用 BLOC 进行状态管理。

In all cases that I use var yyystate = BlocProvider.of(context);在我使用的所有情况下 var yyystate = BlocProvider.of(context); I always add the listen parameter.我总是添加listen参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在此提供程序示例中的此简单提供程序错误中,尝试从小部件树外部侦听提供程序公开的值 - Tried to listen to a value exposed with provider, from outside of the widget tree in this simple provider error in this provider example 试图从小部件树外部侦听提供者公开的值。 但我想听 - Tried to listen to a value exposed with provider, from outside of the widget tree. But I want to listen to it EXCEPTION CAUGHT BY GESTURE 试图从小部件树的外部监听提供者公开的值 - EXCEPTION CAUGHT BY GESTURE Tried to listen to a value exposed with provider, from outside of the widget tree Flutter:从小部件树外部访问提供者 - Flutter: access provider from outside the widget tree 在小部件树外调用提供者方法 - Calling a provider method outside the widget tree 如何在小部件树/小部件 class 之外调用riverpod 提供程序? - How to call a riverpod provider outside of widget tree/widget class? Flutter:在小部件树外的另一个 class 中调用 Provider 方法 - Flutter: Invoking Provider method in another class outside of the widget tree 从外部小部件更新提供程序类 - Updating provider class from outside widget 通过 addPostFrameCallback 的 Flutter Provider 访问表示小部件在小部件树之外,但 flutter inspector 显示否则 - Flutter Provider access via addPostFrameCallback says widget is outside the widget tree but flutter inspector shows otherwise 如何访问一个Widget之外的provider? - How acess provider outside a Widget?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM