Flutter - 在构建期间调用 setState() 或 markNeedsBuild()
Posted
技术标签:
【中文标题】Flutter - 在构建期间调用 setState() 或 markNeedsBuild()【英文标题】:Flutter - setState() or markNeedsBuild() called during build 【发布时间】:2021-05-31 15:56:24 【问题描述】:从 Firebase Cloud 加载帖子时显示错误。我在我的应用程序中使用提供程序
setState() or markNeedsBuild() called during build.
详细错误
════════ Exception caught by foundation library ════════════════════════════════
The following assertion was thrown while dispatching notifications for PostFunctions:
setState() or markNeedsBuild() called during build.
This _InheritedProviderScope<PostFunctions> 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.
我加载帖子时的代码..
Widget feedBody(BuildContext context)
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('posts')
.orderBy('time', descending: true)
.snapshots(),
builder: (context, snapshot)
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: SizedBox(
height: 200.0,
width: 200.0,
child: Lottie.asset('assets/animations/loading.json'),
),
);
else
return loadPosts(context, snapshot);
,
),
height: MediaQuery.of(context).size.height * 0.80,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: constantColors.darkColor.withOpacity(0.6),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(18.0),
topRight: Radius.circular(18.0),
),
),
),
),
);
我的加载邮政编码
Widget loadPosts(
BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot)
return ListView(
children: snapshot.data.docs.map((DocumentSnapshot documentSnapshot)
Provider.of<PostFunctions>(context, listen: false)
.showTimeAgo(documentSnapshot.data()['time']);
return Container(
height: MediaQuery.of(context).size.height * 0.62,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(
top: 8.0,
left: 8.0,
),
child: Row(
children: [
GestureDetector(
onTap: ()
if (documentSnapshot.data()['useruid'] !=
Provider.of<Authenticationss>(context, listen: false)
.getUserUid)
Navigator.pushReplacement(
context,
PageTransition(
child: AltProfile(
userUid: documentSnapshot.data()['useruid'],
),
type: PageTransitionType.bottomToTop,
),
);
,
child: CircleAvatar(
backgroundColor: constantColors.blueGreyColor,
radius: 20.0,
backgroundImage:
NetworkImage(documentSnapshot.data()['userimage']),
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.6,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Text(
documentSnapshot.data()['caption'],
style: TextStyle(
color: constantColors.greenColor,
fontWeight: FontWeight.bold,
fontSize: 16.0),
),
),
Container(
child: RichText(
text: TextSpan(
text: documentSnapshot.data()['username'],
style: TextStyle(
color: constantColors.blueColor,
fontSize: 14.0,
fontWeight: FontWeight.bold,
),
children: <TextSpan>[
TextSpan(
text:
' , $Provider.of<PostFunctions>(context, listen: false).getImageTimePosted.toString()',
style: TextStyle(
color: constantColors.lightColor
.withOpacity(0.8),
),
)
],
),
),
),
],
),
),
),
Container(
width: MediaQuery.of(context).size.width * .2,
height: MediaQuery.of(context).size.height * 0.05,
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('posts')
.doc(documentSnapshot.data()['caption'])
.collection('awards')
.snapshots(),
builder: (context, snapshot)
if (snapshot.connectionState ==
ConnectionState.waiting)
return Center(
child: CircularProgressIndicator(),
);
else
return ListView(
scrollDirection: Axis.horizontal,
children: snapshot.data.docs
.map((DocumentSnapshot documentSnapshot)
return Container(
height: 30.0,
width: 30.0,
child: Image.network(
documentSnapshot.data()['award']),
);
).toList(),
);
,
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
height: MediaQuery.of(context).size.height * 0.45,
width: MediaQuery.of(context).size.width,
child: FittedBox(
child: Image.network(
documentSnapshot.data()['postimage'],
scale: 2,
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Padding(
padding: const EdgeInsets.only(left: 21.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 80.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
GestureDetector(
onLongPress: ()
Provider.of<PostFunctions>(context, listen: false)
.showLikes(
context,
documentSnapshot.data()['caption'],
);
,
onTap: ()
print('adding like');
Provider.of<PostFunctions>(context, listen: false)
.addLike(
context,
documentSnapshot.data()['caption'],
Provider.of<Authenticationss>(context,
listen: false)
.userUid);
,
child: Icon(
FontAwesomeIcons.heart,
color: constantColors.redColor,
size: 22.0,
),
),
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('posts')
.doc(documentSnapshot.data()['caption'])
.collection('likes')
.snapshots(),
builder: (context, snapshot)
if (snapshot.connectionState ==
ConnectionState.waiting)
return Center(
child: CircularProgressIndicator(),
);
else
return Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
snapshot.data.docs.length.toString(),
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
);
,
)
],
),
),
Container(
width: 80.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
GestureDetector(
onTap: ()
Provider.of<PostFunctions>(context, listen: false)
.shotCommentSheets(context, documentSnapshot,
documentSnapshot.data()['caption']);
,
child: Icon(
FontAwesomeIcons.comment,
color: constantColors.blueColor,
size: 22.0,
),
),
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('posts')
.doc(documentSnapshot.data()['caption'])
.collection('comments')
.snapshots(),
builder: (context, snapshot)
if (snapshot.connectionState ==
ConnectionState.waiting)
return Center(
child: CircularProgressIndicator(),
);
else
return Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
snapshot.data.docs.length.toString(),
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
);
,
)
],
),
),
Container(
width: 80.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
GestureDetector(
onLongPress: ()
Provider.of<PostFunctions>(context, listen: false)
.showAwardPresenter(context,
documentSnapshot.data()['caption']);
,
onTap: ()
Provider.of<PostFunctions>(context, listen: false)
.showReward(context,
documentSnapshot.data()['caption']);
,
child: Icon(
FontAwesomeIcons.award,
color: constantColors.yellowColor,
size: 22.0,
),
),
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('posts')
.doc(documentSnapshot.data()['caption'])
.collection('awards')
.snapshots(),
builder: (context, snapshot)
if (snapshot.connectionState ==
ConnectionState.waiting)
return Center(
child: CircularProgressIndicator(),
);
else
return Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
snapshot.data.docs.length.toString(),
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
);
,
)
],
),
),
Spacer(),
Provider.of<Authenticationss>(context, listen: false)
.getUserUid ==
documentSnapshot.data()['useruid']
? IconButton(
icon: Icon(
EvaIcons.moreVertical,
color: constantColors.whiteColor,
),
onPressed: ()
Provider.of<PostFunctions>(context, listen: false)
.showPostOptions(context,
documentSnapshot.data()['caption']);
,
)
: Container(
height: 0.0,
width: 0.0,
),
],
),
),
),
],
),
);
).toList());
【问题讨论】:
【参考方案1】:正如错误所描述的,setState 甚至在构建函数完成之前就被调用了。
当此异常在调试或本地发布模式下出现时,您可能不会在 UI 中看到任何问题。但像这样的例外情况会显示灰屏或其他东西,而不是谷歌播放版本等所需的小部件。
这意味着您正在尝试刷新页面,即使初始小部件已经加载。
为了防止在 build 方法已经在进行中调用 setState,您可以在调用 setState 之前检查您的初始小部件是否正确挂载。为此,只需通过 if 语句将 setState 包装起来:
if(mounted)
setState(()
);
还有一个方法是在构建方法完成后调用。关注这个问题了解更多:Is there any callback to tell me when "build" function is done in Flutter?
【讨论】:
我没有在任何地方使用 setState以上是关于Flutter - 在构建期间调用 setState() 或 markNeedsBuild()的主要内容,如果未能解决你的问题,请参考以下文章
Flutter - 在构建期间调用 setState() 或 markNeedsBuild()
在构建期间调用 setState() 或 markNeedsBuild() - Flutter
Flutter:在构建错误期间调用了 setState() 或 markNeedsBuild()
Flutter :setState() 或 markNeedsBuild() 在构建期间调用