需要帮助追查:Exception while building using Provider in Flutter
Need help chasing down: Exception while building using Provider in Flutter
我正在尝试学习 Flutter 并更加熟悉如何传递数据。所以我这里有这个非常简单的应用程序,它是这个的一种复杂版本:Provider version flutter starter demo
就像我说的,我正在努力结识,我是一个相对绿色的开发者。我创建此演示是为了学习 StateManagement 和 Persistence。
我的目标 post 是获得解决此问题的帮助,并知道我做错了什么。
到目前为止,我已经尝试移动一些东西并进行一些典型的搜索,但与遇到相同错误的其他人相比,我似乎无法具体弄清楚我在这里做错了什么。
该应用程序运行良好,完全符合预期,没有崩溃,就我的绿草眼睛而言,我的代码结构与 Flutter 示例完全一样(关于 Provider StateManagement)。但是我在控制台中收到此错误:
======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for Keeper:
setState() or markNeedsBuild() called during build.
This _InheritedProviderScope<Keeper> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<Keeper>
value: Instance of 'Keeper'
listening to value
The widget which was currently being built when the offending call was made was: Consumer<Keeper>
dirty
dependencies: [_InheritedProviderScope<Keeper>]
第 1 页
class ScreenOne extends StatelessWidget {
static const String id = 'screen_one';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Page One',
),
),
backgroundColor: Colors.grey.shade200,
body: Container(
child: SafeArea(
child: Padding(
padding: EdgeInsets.all(20.0),
child: Center(
child: Column(
children: [
CustomTextBoxes(title: 'Screen One'),
Consumer<Keeper>(
builder: (_, keeper, child) => Text(
'${keeper.pageOneValue}',
style: TextStyle(color: Colors.grey, fontSize: 20.0),
),
),
CustomTextBoxes(title: 'Screen Two'),
Consumer<Keeper>(
builder: (_, keeper, child) => Text(
'${keeper.pageTwoValue}',
style: TextStyle(color: Colors.grey, fontSize: 20.0),
),
),
CustomTextBoxes(title: 'Total'),
Consumer<Keeper>(
builder: (_, keeper, child) => Text(
'${keeper.addCounters()}',
style: TextStyle(color: Colors.grey, fontSize: 20.0),
),
),
SizedBox(
height: 20.0,
),
CustomButton(
text: 'Screen 2',
function: () {
Navigator.pushNamed(context, ScreenTwo.id);
},
),
],
),
),
),
),
),
floatingActionButton: CustomFloatingButton(
function: () {
var counter = context.read<Keeper>();
counter.incrementCounterOne();
},
),
);
}
}
“守护者”
class Keeper with ChangeNotifier {
int pageOneValue = 0;
int pageTwoValue = 0;
int totalValue = 0;
void incrementCounterOne() {
pageOneValue += 1;
notifyListeners();
}
void incrementCounterTwo() {
pageTwoValue += 1;
notifyListeners();
}
int addCounters() {
totalValue = pageOneValue + pageTwoValue;
notifyListeners();
return totalValue;
}
}
主要
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Keeper(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.blue),
initialRoute: ScreenOne.id,
routes: {
ScreenOne.id: (context) => ScreenOne(),
ScreenTwo.id: (context) => ScreenTwo()
},
);
}
}
您的问题在于在 build
方法中调用 addCounters()
。 addCounters()
调用 notifyListeners()
触发 setState()
.
这不能在您的 build
函数中执行。它只能在以后应用户操作的请求执行。例如,在按钮的 onPressed
内,就像您对 incrementCounterOne()
.
所做的那样
您可以使用 getter:
而不是计算和存储两个计数器的总值
管理员:
class Keeper with ChangeNotifier {
int pageOneValue = 0;
int pageTwoValue = 0;
int get totalValue => pageOneValue + pageTwoValue;
void incrementCounterOne() {
pageOneValue += 1;
notifyListeners();
}
void incrementCounterTwo() {
pageTwoValue += 1;
notifyListeners();
}
}
屏幕一:
Consumer<Keeper>(
builder: (_, keeper, child) => Text(
'${keeper.totalValue}', // addCounters()}',
style: TextStyle(color: Colors.grey, fontSize: 20.0),
),
),
我正在尝试学习 Flutter 并更加熟悉如何传递数据。所以我这里有这个非常简单的应用程序,它是这个的一种复杂版本:Provider version flutter starter demo
就像我说的,我正在努力结识,我是一个相对绿色的开发者。我创建此演示是为了学习 StateManagement 和 Persistence。
我的目标 post 是获得解决此问题的帮助,并知道我做错了什么。
到目前为止,我已经尝试移动一些东西并进行一些典型的搜索,但与遇到相同错误的其他人相比,我似乎无法具体弄清楚我在这里做错了什么。
该应用程序运行良好,完全符合预期,没有崩溃,就我的绿草眼睛而言,我的代码结构与 Flutter 示例完全一样(关于 Provider StateManagement)。但是我在控制台中收到此错误:
======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for Keeper:
setState() or markNeedsBuild() called during build.
This _InheritedProviderScope<Keeper> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<Keeper>
value: Instance of 'Keeper'
listening to value
The widget which was currently being built when the offending call was made was: Consumer<Keeper>
dirty
dependencies: [_InheritedProviderScope<Keeper>]
第 1 页
class ScreenOne extends StatelessWidget {
static const String id = 'screen_one';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Page One',
),
),
backgroundColor: Colors.grey.shade200,
body: Container(
child: SafeArea(
child: Padding(
padding: EdgeInsets.all(20.0),
child: Center(
child: Column(
children: [
CustomTextBoxes(title: 'Screen One'),
Consumer<Keeper>(
builder: (_, keeper, child) => Text(
'${keeper.pageOneValue}',
style: TextStyle(color: Colors.grey, fontSize: 20.0),
),
),
CustomTextBoxes(title: 'Screen Two'),
Consumer<Keeper>(
builder: (_, keeper, child) => Text(
'${keeper.pageTwoValue}',
style: TextStyle(color: Colors.grey, fontSize: 20.0),
),
),
CustomTextBoxes(title: 'Total'),
Consumer<Keeper>(
builder: (_, keeper, child) => Text(
'${keeper.addCounters()}',
style: TextStyle(color: Colors.grey, fontSize: 20.0),
),
),
SizedBox(
height: 20.0,
),
CustomButton(
text: 'Screen 2',
function: () {
Navigator.pushNamed(context, ScreenTwo.id);
},
),
],
),
),
),
),
),
floatingActionButton: CustomFloatingButton(
function: () {
var counter = context.read<Keeper>();
counter.incrementCounterOne();
},
),
);
}
}
“守护者”
class Keeper with ChangeNotifier {
int pageOneValue = 0;
int pageTwoValue = 0;
int totalValue = 0;
void incrementCounterOne() {
pageOneValue += 1;
notifyListeners();
}
void incrementCounterTwo() {
pageTwoValue += 1;
notifyListeners();
}
int addCounters() {
totalValue = pageOneValue + pageTwoValue;
notifyListeners();
return totalValue;
}
}
主要
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Keeper(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.blue),
initialRoute: ScreenOne.id,
routes: {
ScreenOne.id: (context) => ScreenOne(),
ScreenTwo.id: (context) => ScreenTwo()
},
);
}
}
您的问题在于在 build
方法中调用 addCounters()
。 addCounters()
调用 notifyListeners()
触发 setState()
.
这不能在您的 build
函数中执行。它只能在以后应用户操作的请求执行。例如,在按钮的 onPressed
内,就像您对 incrementCounterOne()
.
您可以使用 getter:
而不是计算和存储两个计数器的总值管理员:
class Keeper with ChangeNotifier {
int pageOneValue = 0;
int pageTwoValue = 0;
int get totalValue => pageOneValue + pageTwoValue;
void incrementCounterOne() {
pageOneValue += 1;
notifyListeners();
}
void incrementCounterTwo() {
pageTwoValue += 1;
notifyListeners();
}
}
屏幕一:
Consumer<Keeper>(
builder: (_, keeper, child) => Text(
'${keeper.totalValue}', // addCounters()}',
style: TextStyle(color: Colors.grey, fontSize: 20.0),
),
),