【问题标题】:Flutter/Dart - Photo changed but not the URL, therefore Provider's Consumer is not RefreshedFlutter/Dart - 照片已更改,但 URL 未更改,因此提供者的消费者未刷新
【发布时间】:2021-01-26 23:40:30
【问题描述】:

一旦将新照片上传到服务器以替换旧照片,我将使用Provider with ChangeNotifier 提醒Consumer。问题是 URL 保持不变,因为照片只是被覆盖并保持相同的名称。因此,消费者不会识别出任何变化,也不会用新照片刷新旧照片。

如何欺骗 ChangeNotifier 刷新 URL?这是我构建中的Consumer;

  Consumer<SocialProvider>(
             builder: (context, socialProvider, child) {
               return Image.network(socialProvider.currentavatar,
            );
       }),

这是在图库中选择图像并上传以覆盖服务器上旧图像的位置。

    GestureDetector(
              onTap: () async {
                   await socialProvider.loadCurrentUserId();
                   await _listener.openGallery(socialProvider.currentuserid);
                   String updatedavatar = "http://example.com/same_photo.jpg";
                   socialProvider.updateAvatar(updatedavatar);
                  },

这是带有 ChangeNotifier 的 Provider 中的代码;

Future<void> updateAvatar(String avatar) async {
     var box = await Hive.openBox('currentuser');
      box.put('currentavatar', avatar);
      currentavatar = avatar;
      notifyListeners();
     }

任何想法如何欺骗Consumer 相信 url 已更改以便刷新?

【问题讨论】:

    标签: flutter dart flutter-provider flutter-image flutter-change-notifier


    【解决方案1】:

    我相信当有人打电话给notifyListeners() 时Consumer 会重建。您的问题可能出在Image.network(socialProvider.currentavatar,) 中,当一切都没有改变时,颤动会重用相同的渲染对象。您可以尝试添加key:UniqueLey() 以在每次构建时强制重新构建小部件。


    更新一些假设。 这是我尝试重建您的环境的简单代码:

    class SimpleProvider with ChangeNotifier {
      Future<void> reload() async => notifyListeners();
    }
    
    class TestConsumer extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: ChangeNotifierProvider(
            create: (context) => SimpleProvider(),
            child: Consumer<SimpleProvider>(
              builder: (_, simpleProvider, child) {
                print('Consumer build');
                return child; // Here is your Image?
              },
              child: Builder(
                builder: (context) {
                  print('Builder build');
                  return Scaffold(
                    floatingActionButton: FloatingActionButton(
                      onPressed: () {
                        context.read<SimpleProvider>().reload();
                      },
                    ),
                    body: Container(),
                  );
                },
              ),
            ),
          ),
        );
      }
    }
    

    每次点击按钮,SimpleProvider 都会调用notifyListeners() (Future 不是必需的)并且将调用Consumer 中的builder 函数。问题来了:

    1. builder 真的在你使用 notifyListeners 时被调用了吗?

    我假设调用了构建器函数。您仍然可以仔细检查这部分。否则,您必须提供如何称呼它。

    1. 如果调用builder,为什么里面的Image Widget没有重建?

    它是颤振设计的一部分,它尽可能多地重用,以获得更好的性能。有时它使人们感到困惑的是重建没有发生。那就是我猜你的问题在这里。您可以在此处查看视频中的基本机制: https://www.youtube.com/watch?v=996ZgFRENMs&ab_channel=Flutter

    【讨论】:

    • 我尝试将 Consumer 更改为 Hive 侦听器,但它仍然无法正常工作。这是你的意思吗? Image.network('${box.get('currentavatar', defaultValue: 'example.com/default,png')}', key:UniqueKey(),;
    • 它也不适用于消费者 - Consumer( builder: (context, socialProvider, child) { return Image.network(snapshot.data[0], key:UniqueKey(), ) ; } ),
    • 我对您在问题中使用 socialProvider.currentavatar 而不是在评论中的评论感到有些困惑。您的问题是您想在Consumer 中重建builder 函数对吗?在调用notifyListeners() 之后,您是否检查过builder 是否被调用?
    • 很抱歉给您带来了困惑。我一直在尝试不同的东西,包括 Hive 监听器、社交提供者和未来。我带着原来的 socialProvider.currentavatar 回来了。
    • 这是我在 medium.com 的一篇文章中发现的一些有趣的东西 - “因此,唯一键必须仅用于无状态小部件,其中小部件不依赖于内部数据更改。”。所以我猜这就是为什么 key:UniqueKey() 不起作用。
    猜你喜欢
    • 2020-10-03
    • 1970-01-01
    • 2021-03-17
    • 2020-02-06
    • 1970-01-01
    • 2020-09-08
    • 2020-03-02
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多