[英]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.