i have a ChangeNotifireProvider that such that i do pushReplacementNamed(someRoute), then i go back to the screen that holds the provider, i get this error
A Product was used after being disposed.
flutter: Once you have called dispose() on a Product, it can no longer be used.
but if i do pushName(someRoute), it will not throw an error,
Thanks for your answer
You should move your provider above MaterialApp/Navigator.
Otherwise when the route is destroyed, it'll dispose the object created too, which is undesired in your situation
@rrousselGit please can you clarify this , thank you for your quick response
Don't:
MaterialApp(
home: Provider(child: Home()),
)
DO:
Provider(
child: MaterialApp(
child: Home(),
)
)
@rrousselGit ,actually im doing it, i just narrowed down the error to a widget, such that only this widget throws the error
the widge:
@override
Widget build(BuildContext context) {
final product= Provider.of<Product>(context, listen: false);
final cart= Provider.of<Cart>(context);
return ClipRRect(
borderRadius: BorderRadius.circular(10),
//// more code
}
and im rendering it here :
'
return GridView.builder(
padding: const EdgeInsets.all(15),
itemBuilder: (ctx, index) {
return ChangeNotifierProvider(
builder: (c) => products[index],
child: ProductGridItem(),
);
'
this is what is throwing the error, sorry for asking too much, i just started using the provider package, ,
thank yo`
Oh, I see what you're doing.
Don't:
ChangeNotifierProvider(
builder: (c) => products[index],
child: ProductGridItem(),
);
DO:
ChangeNotifierProvider.value(
value: products[index],
child: ProductGridItem(),
);
Thank you so much it works, but it will help a lot if you can tell why the second approach works while the first doesn't, thank you again for replying so fast
The default constructor should be used only to _create_ an object, not to use an existing instance.
Similarly, the second constructor should be used only when you _already have a valure_, not when you want to create one.
thank you so much that did help alot, im kinda that guy that wants to undestand why thats why im asking, i suggest you add the prev comment to the readme ,
Thank you again for your time & quick replies.
Hi, I'm facing a similar issue. In my e-commerce app, I have to load the details for each item individually, but I want the process to feel seamless, so I created my own ItemDetailsBLOC model, and initiated it in my grid view item. So that when, that it starts loading data as soon as the item is rendered, if the user opens any of the item's detail page, the data will already be there or will at least loading will feel shorter.
I get the following error, when I scroll really fast through the GridView.
ItemDetailsBLOC: LoadData: UnexpectedError: A ItemDetailsBLOC was used after being disposed.
Once you have called dispose() on a ItemDetailsBLOC, it can no longer be used.
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: A ItemDetailsBLOC was used after being disposed.
Once you have called dispose() on a ItemDetailsBLOC, it can no longer be used.
#0 ChangeNotifier._debugAssertNotDisposed.<anonymous closure> (package:flutter/src/foundation/change_notifier.dart:105:9)
#1 ChangeNotifier._debugAssertNotDisposed (package:flutter/src/foundation/change_notifier.dart:111:6)
#2 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:200:12)
#3 ItemDetailsBLOC.taskStatus= (package:mega_dot_pk/blocs/item_details_bloc.dart:21:5)
#4 ItemDetailsBLOC.loadData (package:mega_dot_pk/blocs/item_details_bloc.dart:40:7)
<asynchronous suspension>
#5 new ItemDetailsBLOC (package:mega_dot_pk/blocs/item_details_bloc.dart:26:5)
#6 _ItemGridItemState.build.<anonymous closure> (package:mega_dot_pk/widgets/item_grid_item.dart:27:24)
#7 BuilderStateDelegate.initDelegate (package:provider/src/delegate_widget.dart:249:14)
#8 <…>
Below is how I create and pass my ItemDetailsBLOC to the next page. Note, I am passing the BLOC because when I call Navigator.push, the Consumer will not be able to directly fetch this because it's not in the same widget tree.
GridItem (Stateful)
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (_) => ItemDetailsBLOC(widget.item),
child: Consumer<ItemDetailsBLOC>(
builder: (_, bloc, __) => InkWell(
onTap: () => _goToDetails(bloc),
child: _myGridItem(),
),
),
);
ItemDetailsPage (Stateful)
class ItemDetailPage extends StatefulWidget {
final ItemDetailsBLOC bloc;
ItemDetailPage(this.bloc);
@override
_ItemDetailPageState createState() => _ItemDetailPageState();
}
class _ItemDetailPageState extends State<ItemDetailPage> {
@override
Widget build(BuildContext context) => Scaffold(
appBar: _appBar(),
body: _body(widget.bloc),
bottomNavigationBar: _bottomAppBar(),
backgroundColor: Theme.of(context).canvasColor,
);
Oh, I see what you're doing.
Don't:
ChangeNotifierProvider( builder: (c) => products[index], child: ProductGridItem(), );DO:
ChangeNotifierProvider.value( value: products[index], child: ProductGridItem(), );
Thanks so much for this!!!! Worked perfectly
can anybody help please.. for the love of god I can't figure out the issue.
my UserProvider has a firebase snapshot listener which Im calling initializing from my home page.
when the listener gets trigger I get the error.
this is my main
````dart
return LocalizationProvider(
child: MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: AuthProvider(),
),
ChangeNotifierProvider.value(
value: BottomBarProvider(0),
),
ChangeNotifierProvider.value(
value: ChatProvider(),
),
ChangeNotifierProvider.value(
value: TestProvider(),
),
ChangeNotifierProxyProvider
update: (context, auth, previous) => UserProvider(
auth.user, new UserData(), previous.activityResponse),
create: (_) => UserProvider(
new UserData(), new UserData(), new ActivityResponse()),
),
ChangeNotifierProxyProvider
update: (context, auth, previous) => PostProvider(
auth.user,
previous == null ? new PostsResponse() : previous.postResponse,
),
create: (_) => PostProvider(new UserData(), new PostsResponse()),
),
ChangeNotifierProxyProvider
update: (context, auth, previous) => GroupProvider(
previous == null ? new GroupResponse() : previous.groupResponse,
auth.user),
create: (_) => GroupProvider(new GroupResponse(), new UserData()),
),
],
child: Consumer
builder: (ctx, auth, _) => MaterialApp(
builder: (BuildContext context, Widget child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: child,
);
},
title: 'title',
theme: ThemeData(
primarySwatch: Colors.indigo,
// accentColor: Colors.purpleAccent,
// textTheme: ThemeData.dark().textTheme.copyWith(
// title: TextStyle(
// color: Theme.of(context).accentColor,
// fontWeight: FontWeight.bold,
// fontSize: 20,
// ),
// ),
),
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
localizationDelegate
],
supportedLocales: localizationDelegate.supportedLocales,
locale: localizationDelegate.currentLocale,
home: auth.isAuthenticated
? BottomBar()
: FutureBuilder(
future: auth.isAuth(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? Splash()
: Login(),
),
routes: {
// Home.routeName: (context) => Home(new ScrollController()),
Login.routeName: (context) => Login(),
Account.routeName: (context) => Account(),
// Profile.routeName: (context) => Profile(),
// PostsEdit.routeName: (context) => PostsEdit(),
},
),
),
),
``
Unhandled Exception: A UserProvider was used after being disposed.
Once you have called dispose() on a UserProvider, it can no longer be used`
Most helpful comment
Oh, I see what you're doing.
Don't:
DO: