Provider: A Product was used after being disposed. flutter: Once you have called dispose() on a Product, it can no longer be used.

Created on 23 Jul 2019  Â·  11Comments  Â·  Source: rrousselGit/provider

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

Most helpful comment

Oh, I see what you're doing.

Don't:

ChangeNotifierProvider(
  builder: (c) => products[index],
  child: ProductGridItem(),
);

DO:

ChangeNotifierProvider.value(
  value: products[index],
  child: ProductGridItem(),
);

All 11 comments

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`

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BazinC picture BazinC  Â·  6Comments

Vadaski picture Vadaski  Â·  3Comments

mhd-barikhan picture mhd-barikhan  Â·  5Comments

stocksp picture stocksp  Â·  5Comments

hou3172568 picture hou3172568  Â·  4Comments