Flutter/Dart - Photo changed but not the URL, therefore Provider's Consumer is not Refreshed

456 views Asked by At

I'm using Provider with ChangeNotifier to alert a Consumer once a new photo is uploaded to a server replacing an old photo. The problem is that the URL stays the same as the photo is merely overwritten and keeps the same name. Hence the Consumer doesn't recognize that anything has changed and doesn't refresh the old photo with the new one.

How can I trick the ChangeNotifier into refreshing the URL? Heres' the Consumer in my build;

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

Here's where the image is chosen in the Gallery and uploaded to overwrite the old image on the server.

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

And here's the code in the Provider with ChangeNotifier;

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

Any ideas how to trick Consumer into believing the url has changed so that it is refreshed?

1

There are 1 answers

8
yellowgray On

I believe the Consumer will rebuild when someone call notifyListeners(). Your issue may be in Image.network(socialProvider.currentavatar,) that flutter reuse same render object when everything is not change. You can try to add key:UniqueLey() to force rebuild the widget every time it build.


Update with some assumption. Here is the simple code I try to rebuild your environment:

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(),
              );
            },
          ),
        ),
      ),
    );
  }
}

Every time I click the button, SimpleProvider will call the notifyListeners() (Future is not necessary) and the builder function in Consumer will be called. Here come the questions:

  1. Is the builder really called when you use notifyListeners?

I assume the builder function is called. You can still double check this part. Otherwise you must provide how you call it.

  1. If builder is called, why the Image Widget inside it is not rebuilt?

It is part of flutter design that it reuse as much as it could, for better performance. Sometimes it confuse people that the rebuild is not happen. That's where I guess your problem is here. You can check the basic mechanism from video here: https://www.youtube.com/watch?v=996ZgFRENMs&ab_channel=Flutter