[英]Flutter: SnackBar not displayed after calling setState() method
我正在實現這個產品應用程序,用戶可以在其中從他的願望清單中添加產品並將其添加到他們的購物車中。 一旦用戶單擊添加到購物車按鈕,我想從屏幕上刪除產品並顯示“成功” Snackbar
。 由於產品是從 FireBase Firestore 加載和顯示的,因此我刪除該項目並調用setState({});
這樣屏幕上的列表就會更新。 問題是緊跟在setState({});
之后的SnackBar
; 未顯示。
我認為這是因為小部件樹已重建,因此當前的 state 和上下文“消失了”。 我嘗試在網上查找一些信息,但沒有找到任何有用的信息。 我還嘗試使用bool
標志進行解決,一旦用戶單擊“添加到購物車”按鈕,該標志將被設置,並且在setState
上,該標志將一次為真,以在重建小部件樹時顯示SnackBar
,然后轉標志回到關閉狀態,但效果不佳。
我錯過了什么? 調用setState({})
后如何顯示SnackBar
?
這是我的代碼:(有問題的行標有FIXME:
)
final GlobalKey _repaintBoundaryKey = GlobalKey();
final GlobalKey<ScaffoldState> _scaffoldKeyWishList = new GlobalKey<ScaffoldState>();
final Center _circularProgressIndicator = Center(
child: SizedBox(
width: 60,
height: 60,
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightGreen[800]),
)
),
);
@override
Widget build(BuildContext context) {
return Material(
child: FutureBuilder(
future: FirebaseFirestore.instance.collection("Wishlists").doc(FirebaseAuth.instance.currentUser.uid).get(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> wishListSnapshot) {
if (wishListSnapshot.connectionState != ConnectionState.done) {
return _circularProgressIndicator;
} else if (!wishListSnapshot.hasData ||
0 == wishListSnapshot.data.data()['Wishlist'].length) {
return globals.emptyListErrorScreen(context, 'Wishlist');
}
int totalProducts = wishListSnapshot.data.data()['Wishlist'].length;
return Scaffold(
key: _scaffoldKeyWishList,
backgroundColor: Colors.lightGreen[800],
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white,
child: ListView.builder(
itemCount: totalProducts * 2,
shrinkWrap: true,
padding: const EdgeInsets.all(16),
itemBuilder: (BuildContext _context, int i) {
if (i >= 2 * totalProducts) {
return null;
}
if (i.isOdd) {
return Divider(
color: Colors.green,
thickness: 1.0,
);
}
var wishlistIdData = wishListSnapshot.data.data()['Wishlist'];
String productID = wishlistIdData[i ~/ 2];
return FutureBuilder(
future: FirebaseFirestore.instance.collection("Products").doc(productID).get(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> productSnapshot) {
if (wishListSnapshot.connectionState != ConnectionState.done || !productSnapshot.hasData) {
return _circularProgressIndicator;
}
var productData = productSnapshot.data.data()['Product'];
String prodName = productData['name'];
String prodPrice = productData['price'];
String prodDate = productData['date'];
return Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: 0.22,
direction: Axis.horizontal,
actions: <Widget>[
//add to cart
IconSlideAction(
caption: 'Add to cart',
color: Colors.transparent,
foregroundColor: Colors
.amberAccent,
icon: Icons.add_shopping_cart,
onTap: () async {
globals.userCart.add(
globals.Product(
productID,
FirebaseAuth.instance.currentUser.uid,
prodName,
double.parse(prodPrice),
prodDate,
[],
"",
"")
);
///removing product from wishlist
List toRemove = [];
toRemove.add(productID);
await FirebaseFirestore.instance
.collection('Wishlists')
.doc(FirebaseAuth.instance.currentUser.uid)
.get()
.then((value) async {
List<dynamic> list = List
.from(value
.data()['Wishlist']);
list
..removeWhere((e) =>
toRemove.contains(e));
await FirebaseFirestore.instance
.collection('Wishlists')
.doc(FirebaseAuth.instance.currentUser.uid)
.update(
{'Wishlist': list});
});
setState(() {
///to update the list on screen
});
//FIXME: snackbar not displayed after setState!
///showing snackbar upon completion
_scaffoldKeyWishList
.currentState
.showSnackBar(
SnackBar(
content: Text(
'Product Successfully Added to Cart!',
style: GoogleFonts
.lato(
fontSize: 13.0,
color: Colors
.white
),
),
behavior: SnackBarBehavior
.floating,
action: SnackBarAction(
label: 'Checkout',
textColor: Colors
.lime,
onPressed: () =>
showDialog(
context: context,
builder: (
BuildContext context) {
return CustomDialogBox();
},
),
),
)
);
},
),
],
child: ListTile(
title: Text(prodName,
style: GoogleFonts.lato(
fontSize: 18.0,
color: Colors.black,
),
),
subtitle: Text(prodPrice + "\$",
style: GoogleFonts.lato(
fontSize: 13.5,
color: Colors.grey,
),
),
visualDensity: VisualDensity
.adaptivePlatformDensity,
),
);
},
);
},
),
)
)
]
)
)
);
}
)
);
}
就我而言,我在構建小部件的構建方法完成過程之前調用了setState
方法。
如果您在構建method
完成之前以及在許多其他情況下顯示snack bar
或alert
對話框,您可能會遇到此error
。 所以在這種情況下使用下面的回調 function。
WidgetsBinding.instance.addPostFrameCallback((_) {
// add your snackbar code here
});
或者您也可以使用具有相同功能的 SchedulerBinding。
SchedulerBinding.instance.addPostFrameCallback((_) {
// add your code here of snackbar.
});
或者你也可以試試這個(我不確定這個)
if(mounted){
//add your code here of snackbar
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.