Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a method with Provider.of(context) inside of dispose() method cause "Looking up a deactivated widget's ancestor is unsafe."

Tags:

When I tried to call a method inside of State dispose method like below.

  @override
  void dispose() {
    Provider.of<AppProvider>(context, listen: false).close();
    super.dispose();
  }

I got this.

The following assertion was thrown while finalizing the widget tree:
Looking up a deactivated widget's ancestor is unsafe.

At this point the state of the widget's element tree is no longer stable.

To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

When the exception was thrown, this was the stack
#0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> 
package:flutter/…/widgets/framework.dart:3508
#1      Element._debugCheckStateIsActiveForAncestorLookup 
package:flutter/…/widgets/framework.dart:3522
#2      Element.getElementForInheritedWidgetOfExactType 
package:flutter/…/widgets/framework.dart:3588
#3      Provider.of 
package:provider/src/provider.dart:219
#4      _MySecondPageState.dispose 
package:test_space/main.dart:138
...

This is my example AppProvider

class AppProvider {
  close() {}
}

and I wrapped MaterialApp with AppProvider

return Provider<AppProvider>(
      create: (_) => AppProvider(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: HomeScreen(),
        },
      ),
    );

I'm not sure how to do this To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method. I'm currently using provider: ^4.0.2.

I used to do it the same, using Provider.of(context) inside of dispose(), without this exception before. Is this because new flutter version? Also, I realized there is the deactivate() method, should I use deactivate() method instead of dispose() method?

[UPDATED]

  AppProvider _appProvider;
  @override
  void didChangeDependencies() {
    _appProvider = Provider.of<AppProvider>(context, listen: false);
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    _appProvider.close();
    super.dispose();
  }

I could also use deactivate in a certain case

  @override
  void deactivate() {
    Provider.of<AppProvider>(context, listen: false)
        .close();
    super.deactivate();
  }
like image 787
user12208004 Avatar asked Feb 03 '20 11:02

user12208004


People also ask

How do I call a provider in dispose flutter?

To dispose provider controller and delete it in flutter You can Just Destroy Provider Listener by setting listen: false in your Provider Just use the below line: provider. of(context). (listen: false) Now, Your provider controller will be disposed of.

Do I need to dispose TextEditingController?

Remember to dispose of the TextEditingController when it is no longer needed. This will ensure we discard any resources used by the object. This example creates a TextField with a TextEditingController whose change listener forces the entered text to be lower case and keeps the cursor at the end of the input.

What dispose flutter?

Flutter – dispose() Method with Example Dispose is a method triggered whenever the created object from the stateful widget is removed permanently from the widget tree. It is generally overridden and called only when the state object is destroyed.


1 Answers

It seems like you are trying to close something which is defined in your AppProvider class. If AppProvider class is extending ChangeNotifier, the change notifier class provides dispose method, you can override it and then call the close function inside the AppProvider class only.

like image 99
Gautam Kumar Avatar answered Sep 17 '22 11:09

Gautam Kumar