Reputation: 31
The following assertion was thrown building ProductList(dirty): setState() or markNeedsBuild() called during build.
This Overlay 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: Overlay-[LabeledGlobalKey#82394] state: OverlayState#6588e(entries: [OverlayEntry#76289(opaque: true; maintainState: false), OverlayEntry#e77e5(opaque: false; maintainState: true), OverlayEntry#6b5f4(opaque: true; maintainState: false), OverlayEntry#7123e(opaque: false; maintainState: true), OverlayEntry#89745(opaque: false; maintainState: false), OverlayEntry#16a91(opaque: false; maintainState: true), OverlayEntry#f64eb(opaque: false; maintainState: false), OverlayEntry#9ff75(opaque: false; maintainState: true)]) The widget which was currently being built when the offending call was made was: ProductList dirty.
This was the error.
While down here is the widget
class ProductList extends StatelessWidget {
final String imageurl;
final String item;
final String subtitle;
final Function press;
const ProductList({Key? key, required this.imageurl, required this.item, required this.subtitle, required this.press}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: GestureDetector(
onTap: press(),
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: AssetImage(imageurl),
),
title: Text(item),
subtitle: Text(subtitle),
),
),
);
}
}
and here is the widget where the press function is used
import 'package:flutter/material.dart';
import 'package:moni_test/pages/product/pages/gaming.dart';
import 'package:moni_test/pages/product/productlistitem.dart';
class ProductMenu extends StatefulWidget {
const ProductMenu({Key? key}) : super(key: key);
@override
_ProductMenuState createState() => _ProductMenuState();
}
class _ProductMenuState extends State<ProductMenu> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.only(top: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
ProductList(
press: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return Gaming();
}));
},
imageurl: "assets/images/kindpng_174783.png",
item: "Gaming",
subtitle: "Consoles, Controllers",),
SizedBox(
height: 20,
),
ProductList(
press: () {},
imageurl: "assets/images/kindpng_4886049.png",
item: "Sneakers",
subtitle: "Puma, Nike, Addidas")
],
),
),
);
}
}
Upvotes: 0
Views: 196
Reputation: 390
wrap setstate with addPostFrameCallback
WidgetsBinding.instance.addPostFrameCallback((callback) {
});
Upvotes: 0
Reputation: 78
onTap: press(),
shouldn't have the trailing (), as this will run the function during build, which is likely what is causing your error. You want to store the function signature (tear-off) for dart to run later, rather than run it immediately.
If that's giving you errors (onTap
will only accept a VoidCallback?
so sometimes your function might not match this signature) you can wrap it in a closure
:
ontap: (){press();}
which will have your desired effect.
Other comments about wrapping addPostFrameCallback
around your problematic code can also be useful in other circumstances (say, you want to want to modify the content of the widget tree later on during build()
) but in this case I'm going to assume it's the function being called when it should be a tear-off instead.
Try this video for some background on tearoffs and closures. You might find something useful here! https://www.youtube.com/watch?v=OmCaloD7sis&t=147s
Upvotes: 1