flutter 为什么Hero不能与多提供商一起使用?

nqwrtyyt  于 2022-11-17  发布在  Flutter
关注(0)|答案(3)|浏览(154)

我有卡片列表。当我点击卡片时,BoxViewPage打开。
如果同时使用Hero和多提供程序,则会出现错误,
但是,
如果我分别使用Hero和MultiProvider,一切都能正常工作
为什么?

卡片清单:

return Hero(
      tag: box.ID,
      child: InkWell(
        child: selectBoxSize(viewType),
        onTap: () async {
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (BuildContext context) => MultiProvider(
                providers: [
                  ChangeNotifierProvider<Archive>.value(value: archive),
                  ChangeNotifierProvider<Box>.value(value: box),
                ],
                builder: (context, child) => BoxViewPage(),
              ),
            ),

内部框视图页:

class BoxCardView extends StatefulWidget {
  const BoxCardView({Key key}) : super(key: key);
  @override
  _BoxCardViewState createState() => _BoxCardViewState();
}

class _BoxCardViewState extends State<BoxCardView> {
  @override
  Widget build(BuildContext context) {
    final box = Provider.of<Box>(context);
    return Hero(
      tag: box.ID,
      child: Card(
        clipBehavior: Clip.antiAlias,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12.0),
        ),
        margin: EdgeInsets.all(12),
        child: Column(
          children: <Widget>[
            Expanded(child: WidgetEditPhotosScrollHoriz()),
            WidgetNameDescrTagsEdit(),
          ],
        ),
      ),
    );
  }
}

错误:

如果验证未找到提供程序异常(错误:在此Widget EditPhotosScrollHoriz Widget上方找不到正确的提供者
这是因为您使用的BuildContext不包含您选择的提供程序。

  • 您在main.dart中添加了新的提供程序并执行了热重新加载。要修复此问题,请执行热重新启动。
  • 您尝试读取的提供程序位于不同的路由中。

提供者是“有范围的”。所以如果你在一个路由中插入一个提供者,那么其他路由将无法访问这个提供者。

  • 您使用的BuildContext是您尝试读取之提供者的上阶。

确保WidgetEditPhotosScrollHoriz位于MultiProvider/Provider下。这通常发生在创建提供程序并尝试立即读取它时。
例如,取代:

Widget build(BuildContext context) {
  return Provider<Example>(
    create: (_) => Example(),
    // Will throw a ProviderNotFoundError, because `context` is associated
    // to the widget that is the parent of `Provider<Example>`
    child: Text(context.watch<Example>()),
  ),
}

考虑如下使用builder

Widget build(BuildContext context) {
  return Provider<Example>(
    create: (_) => Example(),
    // we use `builder` to obtain a new `BuildContext` that has access to the provider
    builder: (context) {
      // No longer throws
      return Text(context.watch<Example>()),
    }
  ),
}

如果这些解决方案都不起作用,请考虑寻求有关StackOverflow的帮助:(第10页)

pdsfdshx

pdsfdshx1#

据我所知,我认为你的问题也是一个典型的,而使用提供商。
我总是建议在应用程序的根目录下使用provider(在MaterialApp之上),这主要是使用它而不会遇到错误的最佳方式。
您可以看到这里实际发生了什么,提供程序基于层次结构工作(它们为所有的小部件和子小部件提供了一个特定的值),我相信你也期待着这一点,但是当我们使用导航器而不是小部件之间的父子关系时,它更像是页面之间的兄弟关系。注意,我在这里使用了页面这个词。当您导航到当前位于导航堆栈顶部的新页面时,您案例中的提供程序仅向您使用它的特定页面的子小部件提供值,而该页面不是子小部件,而是一种同级关系,因此您无法在此处访问提供程序。
如果您不明白这一点,请不要担心,最简单的解决方案和可视化方法就是在浏览器上打开dart开发工具,在Widget Inspector中,检查Widget层次结构,您会发现您要使用提供程序提供的值的Widget不在该层次结构之下,现在您只需要弄清楚您应该做什么来实现它。
我可以给予的一个解决方案是在应用程序的根(Above MaterialApp)使用提供程序。

pxy2qtax

pxy2qtax2#

你能在你的卡片列表文件中试试这个吗:

MaterialPageRoute(
              builder: (BuildContext context) => MultiProvider(
                providers: [
                  ChangeNotifierProvider<Archive>(
                    create: (BuildContext context) => Archive()
                  ),
                  ChangeNotifierProvider<Box>(
                    create: (BuildContext context) => Box()
                  ),
                ],
                builder: (context, child) => BoxViewPage(),
              ),
            ),
cngwdvgl

cngwdvgl3#

我终于解决了从供应商切换到riverpod,它的工作也很好与英雄。谢谢
https://pub.dev/packages/riverpod

相关问题