flutter 在dispose()方法中调用具有Provider.of(context)的方法会导致“查找已停用小部件的祖先是不安全的”,

bvn4nwqk  于 2023-01-27  发布在  Flutter
关注(0)|答案(4)|浏览(279)

当我尝试调用State dispose方法内部的方法时,如下所示。

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

我来吧。

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
...

这是我的示例AppProvider

class AppProvider {
  close() {}
}

我用AppProvider Package 了材料应用程序

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

我不知道如何做这个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.我目前正在使用provider: ^4.0.2
我以前也是这样做的,**在dispose()**中使用Provider. of(context),之前没有这个异常。这是因为新的flutter版本吗?另外,我意识到有deactivate()方法,我应该使用deactivate()方法而不是dispose()方法吗?

  • [已更新]*
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();
  }
qco9c6ql

qco9c6ql1#

您似乎正在尝试关闭在AppProvider类中定义的某个对象。如果AppProvider类正在扩展ChangeNotifier,则更改通知程序类提供dispose方法,您可以重写该方法,然后仅在AppProvider类中调用close函数。

pobjuy32

pobjuy322#

据我所知,这种行为是很久以前的事了,我通常使用after_layout来解决它,如下所示:

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> with AfterLayoutMixin {
  AppProvider _appProvider;

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

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

  @override
  Widget build(BuildContext context) {
    return Container(
      // ...
    );
  }
}
tzcvj98z

tzcvj98z3#

如果需要在离开上下文之前释放某些内容,可以在willPopScope中释放它

WillPopScope(
    onWillPop: () {
       context.read<AppProvider().myController?.dispose();
       Navigator.pop(context);
       return Future.value(false);
    },
    child: ...,
 )
mkshixfv

mkshixfv4#

您应该考虑使用Provider.dispose回调函数,它会在从小部件树中卸载提供程序时调用:

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

相关问题