Reputation: 291
I'm using MultiProvider
and I get this error:
Unhandled Exception: A Products was used after being disposed. Once you have called dispose() on a Products, it can no longer be used.
Here is my main.dart file. What is wrong with this structure?
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Auth(),
),
ChangeNotifierProxyProvider<Auth, Products>(
update: (ctx, auth, previousProducts) => Products(
auth.token,
auth.userId,
previousProducts == null ? [] : previousProducts.items,
),
),
ChangeNotifierProvider.value(
value: Cart(),
),
ChangeNotifierProxyProvider<Auth, Orders>(
update: (ctx, auth, previousOrders) => Orders(
auth.token,
auth.userId,
previousOrders == null ? [] : previousOrders.orders,
),
),
],
child: Consumer<Auth>(
builder: (ctx, auth, _) => MaterialApp(
title: 'MyShop',
theme: ThemeData(
primarySwatch: Colors.purple,
accentColor: Colors.deepOrange,
fontFamily: 'Lato',
),
home: auth.isAuth
? ProductOverviewScreen()
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? SplashScreen()
: AuthScreen(),
),
routes: {
ProductDetailScreen.routeName: (ctx) => ProductDetailScreen(),
CartScreen.routeName: (ctx) => CartScreen(),
OrdersScreen.routeName: (ctx) => OrdersScreen(),
UserProductsScreen.routeName: (ctx) => UserProductsScreen(),
EditProductsScreen.routeName: (ctx) => EditProductsScreen(),
},
),
),
);
}
}
Upvotes: 11
Views: 9813
Reputation: 4750
use yourProvider.value Instead of Create
itemBuilder: (ctx, index) => ChangeNotifierProvider.value(
value: products[index],
child: ProductItem(),
),
itemCount: products.length,
);
Upvotes: 23
Reputation: 8757
Do it like this for example:
return MaterialPageRoute(
builder: (_) => ChangeNotifierProvider<EntryPermitViewModel>.value(
value: EntryPermitViewModel(),
child: const EntryPermitScreen(),
),
);
Upvotes: 2
Reputation: 1473
add delay for Products provider in ProductsOverviewScreen;
@override
void initState() {
Future.delayed(Duration(seconds: 1)).then((_) {
Provider.of<Products>(context, listen: false).fetchAndSetProducts();
});
super.initState();
}
Upvotes: 1
Reputation: 21
This is how you can fix it
GridView.builder(
padding: const EdgeInsets.all(10),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10),
itemBuilder: ((context, i) => ChangeNotifierProvider.value( // <--
value: productsItems[i],
child: ProductItem(),
)),
itemCount: productsItems.length,
);
}
Upvotes: 2
Reputation: 101
I was also getting the same error and I resolved it by:
ChangeNotifierProvider<"Provider name">.value(value:<PassedValue>);
It seems ChangeNotifierProvider creates an instance of the provider and when its work is done dispose() method is called and therefore, that instance is cleared with ChangeNotifierProvider.value, that's not the case and we are able to re-use the earlier created instance.
Here are the official docs: https://pub.dev/packages/provider
Upvotes: 2
Reputation: 1
Use
Navigator.of(context).pushNamed('/');
In your drawer where you called logout
.
This will fix that
Thank you..
Upvotes: -1
Reputation: 11
I think you have to add Products Provider to providers: [] above proxy providers as the definition of Auth Provider like the following:
providers: [
ChangeNotifierProvider<Auth>.value(
value: Auth(),
ChangeNotifierProvider<Products>.value(
value: Products(),
ChangeNotifierProxyProvider<Auth, Products>(
update: (ctx, auth, previousProducts) => Products(
auth.token,
auth.userId,
previousProducts == null ? [] : previousProducts.items,
),
),
ChangeNotifierProvider<Cart>.value(
value: Cart(),
),
ChangeNotifierProxyProvider<Auth, Orders>(
update: (ctx, auth, previousOrders) => Orders(
auth.token,
auth.userId,
previousOrders == null ? [] : previousOrders.orders,
),
),
],
Upvotes: 0