FilledStacks / flutter-tutorials

The repo contains the source code for all the tutorials on the FilledStacks Youtube channel.
MIT License
4.75k stars 1.76k forks source link

Unhandled Exception: Once you have called dispose() it can no longer be used. #49

Closed niklas-b closed 4 years ago

niklas-b commented 4 years ago

Hi,

Im getting the following error messages after implementing the CRUD code:

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: A HomeViewModel was used after being disposed. E/flutter (13683): Once you have called dispose() on a HomeViewModel, it can no longer be used.

Do you have any suggestions on how to solve this?

Thanks!

FilledStacks commented 4 years ago

You're disposing your viewmodel. Either use ChangeNotifierProvider.value, which can be used by passing reuse=true into the ViewModelProvider.withConsumer constructor. Or you have to remove and dispose functionality that calls super.dispose.

niklas-b commented 4 years ago

Thanks for the feedback. I'm not sure if I understand how I'd do this. Would it be possible for you to include the updated code in the repository or including the update in the next tutorial? Thanks!!

FilledStacks commented 4 years ago

It's been answered in the issues. Check in there how it wss handled before it's the same solution. I'll be making a full architecture series coming up that will share patterns I'm currently using while developing 4 production apps with the FilledStacks team. It will be done after this firebasr series and will go over a full application with a lot of common features.

It's gonna be a few months down the line so check the issues for the viewmodel solution that's been discussed before.

-Dane

Get Outlook for Androidhttps://aka.ms/ghei36


From: niklas-b notifications@github.com Sent: Thursday, March 19, 2020 5:45:52 PM To: FilledStacks/flutter-tutorials flutter-tutorials@noreply.github.com Cc: Dane Mackier dane.mackier@outlook.com; Comment comment@noreply.github.com Subject: Re: [FilledStacks/flutter-tutorials] Unhandled Exception: Once you have called dispose() it can no longer be used. (#49)

Thanks for the feedback. I'm not sure if I understand how I'd do this. Would it be possible for you to include the updated code in the repository or including the update in the next tutorial? Thanks!!

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/FilledStacks/flutter-tutorials/issues/49#issuecomment-601253381, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AA3M72SDAECPBWGOQQVRUDTRII43BANCNFSM4LO4BCUQ.

niklas-b commented 4 years ago

Thanks Dane, I was both searching the issues and read them but couldn't find the solution written down anywhere. Would you mind sharing the link?

FilledStacks commented 4 years ago

@niklas-b seems that I also can't find it. Basically your viewmodel is being disposed when it shouldn't so you can use the .value constructor for the ChangeNotifierProvider to ensure that doesn't happen. Or override your viewmodel's dispose and make sure it doesn't call super.dispose.

aizazzaheer commented 4 years ago

@niklas-b go to the homeview.dart, and modify it to be like this:

viewModel: HomeViewModel(), reuseExisting: true, // add this one onModelReady: (model) => model.listenToRealTimePosts(),

This way, it will not dispose the viewmodel and will reuse the same instance next time when you come back to this view.

@FilledStacks looking forward to the next architecture series, they have been so helpful and I've already finished one production app using it, thanks so much and keep up the hard work brother :)

niklas-b commented 4 years ago

@FilledStacks thanks for looking into it. I greatly appreciate your work. This architecture is excellent. Just takes some time to wrap your head around for a beginner! ;)

niklas-b commented 4 years ago

@aizazzaheer Thank you so much for posting this code. Exactly what I need!

Unfortunately, when I add reuseExisting I get an error saying that the named parameter isn't defined.

Here's what the code I'm using looks like right now:

class HomeView extends StatelessWidget { const HomeView({Key key}) : super(key: key);

@override Widget build(BuildContext context) { return ViewModelProvider.withConsumer( viewModel: HomeViewModel(), reuseExisting: true, onModelReady: (model) => model.listenToPosts(), builder: (context, model, child) => Scaffold( ...

Very grateful for any and all help!

mrcprgt commented 4 years ago

@niklas-b I was getting the error till I manually changed my provider version to the latest one which is 4.0.4 in pubspec.yaml. I think that parameter was added in a recent update?

My error currently is that after navigating from a view, onModelReady does not run. Now my view is stuck on a circularloadingindicator.

Any help would be appreciated. Thank you!

niklas-b commented 4 years ago

Thanks for your reply @mrcprgt! Upgrading Provider to 4.0.4 does unfortunately not resolve my issue. And as we're not getting the same error, it's difficult for me to help you. Are you getting any error messages that you could share, or does the app just "freeze"?

FilledStacks commented 4 years ago

@niklas-b if you're using the provider_architecture package you can set reuseExisting to true and it won't dispose your viewmodel.

niklas-b commented 4 years ago

Thanks for the help everyone! The answer lied in the answers of both @aizazzaheer and @mrcprgt. I needed to both upgrade Provider and use 'reuseExisting: true'

basilmariano commented 4 years ago

@niklas-b seems that I also can't find it. Basically your viewmodel is being disposed when it shouldn't so you can use the .value constructor for the ChangeNotifierProvider to ensure that doesn't happen. Or override your viewmodel's dispose and make sure it doesn't call super.dispose.

This works! ) But is there any side effects on not calling super.dispose? (e.g) memory management issues

FilledStacks commented 4 years ago

@basilmariano if you need to dispose a stream or anything like that it won't be called. But if you're wanting it to stay alive you probably have nothing you want to dispose.

fransiskapw commented 3 years ago

In case someone still experiencing the issue, what works for me was to follow the suggestion to use the ChangeNotifierProvider.value, with changes shown below (base_view.dart):

Change

  Widget build(BuildContext context) {
    return ChangeNotifierProvider<T>(
        create: (context) => model,
        child: Consumer<T>(builder: widget.builder));
  }

to

  Widget build(BuildContext context) {
    return ChangeNotifierProvider<T>.value(
        value: model,
        child: Consumer<T>(builder: widget.builder));
  }