I'm applying the Provider pattern to manage the state of my application So I have a ListView of CartItem and when I dismiss the CartItem from it a ProviderNotFoundException occur the logic and the code seems fine to me and I don't know where the problem exactly belongs .
I tried to change the Dismissed widget with an IconButton near my CartItem widget and the same problem occur .
here you can find My code :
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/cart.dart';
class CartItem extends StatelessWidget {
final String id;
final String productId;
final double price;
final int quantity;
final String title;
CartItem(this.id, this.productId, this.price, this.quantity, this.title);
@override
Widget build(BuildContext context) {
return Dismissible(
key: ValueKey(id),
background: Container(
color: Theme.of(context).colorScheme.onSecondary,
alignment: Alignment.centerRight,
padding: const EdgeInsets.only(right: 20),
margin: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 4,
),
child: const Icon(
Icons.delete,
color: Colors.white,
size: 40,
),
),
direction: DismissDirection.endToStart,
onDismissed: (direction) {
Provider.of<Cart>(context, listen: false).removeItem(productId);
},
child: Card(
margin: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 4,
),
child: Padding(
padding: const EdgeInsets.all(8),
child: ListTile(
leading: CircleAvatar(
child: Padding(
padding: const EdgeInsets.all(5),
child: FittedBox(child: Text('\$${price}'))),
),
title: Text(title),
subtitle: Text('Total: \$${(price * quantity)}'),
trailing: Text('$quantity x'),
),
),
),
);
}
}
import 'package:flutter/foundation.dart';
class CartItem {
final String id;
final String title;
final int quantity;
final double price;
CartItem(
this.id,
this.title,
this.price,
this.quantity,
);
}
class Cart with ChangeNotifier {
Map<String, CartItem> _items = {};
Map<String, CartItem> items() {
return {..._items};
}
int get itemCount {
return _items.length;
}
double get totalAmount {
double total = 0.0;
_items.forEach((key, cartItem) {
total += cartItem.price * cartItem.quantity;
});
return total;
}
void addItem(String productId, double price, String title) {
if (_items.containsKey(productId)) {
//change the quantity ...
_items.update(
productId,
(existingCartItem) => CartItem(
existingCartItem.id,
existingCartItem.title,
existingCartItem.price,
existingCartItem.quantity + 1),
);
notifyListeners();
} else {
_items.putIfAbsent(
productId,
() => CartItem(
DateTime.now().toString(),
title,
price,
1,
));
notifyListeners();
}
}
void removeItem(String productId) {
_items.remove(productId);
notifyListeners();
}
void clear() {
_items = {};
notifyListeners();
}
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../Providers/orders.dart';
import '../screens/cart_screen.dart';
import './screens/product_detail_screen.dart';
import './screens/products_overview_screen.dart';
import './Providers/products_provider.dart';
import './Providers/cart.dart';
import './screens/orders_screen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
`//The ChangeNotifierProvider is a widget that makes us listen` `whenever that class updates only the child widget will rebuid`
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
//if we use ChangeNotifierProvider() widget and need
//create: (context) => Products(),
//or use ChangeNotifierProvider.value() and the value
attribute we use this shortcut
//because we don't need the context argument of the
function we were creating using ChangeNotifierProvider() widget
value: Products(),
),
ChangeNotifierProvider<Cart>(create: (_) => Cart()),
/*ChangeNotifierProvider.value(
value: Cart(),
),*/
ChangeNotifierProvider.value(
value: Orders(),
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Shop app',
theme: ThemeData(
primarySwatch: Colors.purple,
accentColor: Colors.deepOrange,
colorScheme: const ColorScheme.light(
primary: Colors.purpleAccent, onSecondary: Colors.deepOrange),
fontFamily: 'Lato',
textTheme: ThemeData.light().textTheme.copyWith(
bodyLarge:
const TextStyle(color: Color.fromRGBO(25, 51, 51, 1)),
bodySmall:
const TextStyle(color: Color.fromRGBO(25, 51, 51, 1)),
titleLarge: const TextStyle(
fontSize: 20.0,
fontFamily: 'lato',
fontWeight: FontWeight.bold,
),
titleMedium: const TextStyle(
fontFamily: 'Raleway',
fontWeight: FontWeight.bold,
color: Colors.white70,
fontSize: 21.0,
),
),
),
home: ProductsOverviewScreen(),
routes: {
ProductDetailScreen.routeName: (ctx) => ProductDetailScreen(),
CartScreen.routeName: (ctx) => CartScreen(),
OrdersScreen.routeName: (ctx) => const OrdersScreen(),
},
),
);
}
}