So, I have a problem when remove icon is pressed. RemoveProduct is called and succesfully remove my product form list, but the setState function doesn’t refresh entyre widget as I want, and product still on the screen even it’s removed by the cartList.
The cart class contains two methods for adding and removing a product from the cart list, respectively. The AddProduct method adds the product to the list and calls notifyListeners to notify its listeners that the cart has been updated. Similarly, the RemoveProduct method removes the product from the list and calls notifyListeners to notify its listeners that the cart has been updated.
The cartPage class is a StatefulWidget that displays the cart contents. It takes an instance of the cart class as a parameter and uses it to build a ListView.builder that displays the contents of the cart
Here is the code:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'product.dart';
import 'theme_data.dart';
class cart extends ChangeNotifier{
List<Product> cartList=[];
cart();
void AddProduct(Product product)
{
cartList.add(product);
notifyListeners();
}
void RemoveProduct(Product product)
{
cartList.remove(product);
notifyListeners();
}
}
class cartPage extends StatefulWidget {
cart myCart;
@override
cartPage({required this.myCart,});
State<cartPage> createState() => _cartPageState();
}
class _cartPageState extends State<cartPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Cos"),
),
body: SingleChildScrollView(
child:
Container(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
itemCount: widget.myCart.cartList.length,
itemBuilder: (BuildContext context, int index) {
final product = widget.myCart.cartList[index];
return cartWidget(product: widget.myCart.cartList[index], productCart: widget.myCart,);
},
),
),
),
);
}
}
class cartWidget extends StatefulWidget {
Product product;
cart productCart;
cartWidget({
Key? key,
required this.product,
required this.productCart
}) : super(key: key);
@override
State<cartWidget> createState() => _cartWidgetState();
}
class _cartWidgetState extends State<cartWidget> {
var qty = ['1', '2', '3', '4'];
late String _selectedValue=qty[0];
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Container(
margin: const EdgeInsets.fromLTRB(0, 15, 0, 0),
padding: const EdgeInsets.fromLTRB(10, 5, 5, 5),
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(10),
boxShadow: const [
BoxShadow(
spreadRadius: 1,
blurRadius: 5,
offset: Offset(0, 1), // changes position of shadow
),
]),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 6,
child: Text(
widget.product.name,
style: TextStyle(
color: MyTheme.textColor(context),
),
),
),
Expanded(
flex: 1,
child: DropdownButton(
value: _selectedValue,
items: qty.map(
(e){
return DropdownMenuItem(value: e, child: Text(e, style: TextStyle(color: MyTheme.textColor(context)),),);
}
).toList(),
onChanged: (val){
setState(() {
_selectedValue = val as String;
});
},
)
),
Expanded(
flex: 1,
child: IconButton(
onPressed: () {
widget.productCart.RemoveProduct(widget.product);
setState(() {});
},
icon: Icon(
Icons.remove_circle_rounded,
color: MyTheme.buttonColor(context),
))),
],
),
Row(children: [
Text(
'${widget.product.price} lei',
style: TextStyle(
color: MyTheme.buttonColor(context),
),
),
]),
],
),
),
);
}
}
}
2
Answers
What you need to do is to consume the changenotifier with a consumer so that your view updates with changes to the notifier. I have modified your code to match.
I have registered the changenotifier and provided it to your view while also wrapping it with a consumer so the view update on notifylisteners.
I think the reason is because you are not using the required way of updating your UI with
Provider
. SetState will not work at that point. Use a consumer widget which will update the value under it’s widget tree.