Flutter/Dart - 如何在其他屏幕上使用图像选择器更新图像

Flutter/Dart - How to update Image after Image Picker on other Screens

我正在使用 Flutter 的 Image Picker 插件来允许用户更改他们的头像。当他们进入他们的帐户页面时,他们会看到他们的常规头像照片,顶部有一个相机图标。单击相机图标将允许他们从他们的相机拍摄照片或从他们的图库中选择一个新的头像。选择新的后,头像照片会自动更新。但是,当离开他们的帐户页面时,旧头像在应用程序的其余部分都是可见的。我将 ProviderChange NotifierConsumers 一起用于其他地方的头像。但问题是我只能在构建中访问 Provider,所以我不知道我可以在我的代码中在哪里调用 Provider。除此之外,我在应用程序周围使用的头像来自互联网 url。使用 Image Picker 选择后,新头像照片将上传到服务器。新照片的名称将替换旧照片的名称。因此我的应用程序甚至不知道有什么改变。即使重新加载页面也不起作用。但是,如果我热重启我的应用程序,则会出现新的头像照片。有什么想法吗?

这是图像选择器代码;

class Picker extends StatefulWidget {
  Picker({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _PickerState createState() =>  _PickerState();
}

class _PickerState extends State<Picker>
    with TickerProviderStateMixin,ImagePickerListener{

  File _image;
  AnimationController _controller;
  ImagePickerHandler imagePicker;

  @override
  void initState() {
    super.initState();
    _controller =  AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );

    imagePicker= ImagePickerHandler(this,_controller);
    imagePicker.init();

  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var socialProvider = Provider.of<SocialProvider>(context);
    return  Container(
      child:  GestureDetector(
        onTap: () => imagePicker.showDialog(context),
        child:  Center(
            child: Stack(
              children: <Widget>[
                Center(
                      child: _image == null?
                          Consumer<SocialProvider>(
                          builder: (context, socialProvider, child) {
                            return
                              Image.network(socialProvider.currentavatar,
                              width: 200,
                              height: 200,
                            );
                          }) :
                              Container(
                              height: 200.0,
                              width: 200.0,
                              decoration:  BoxDecoration(
                              color: Colors.grey,
                              image:  DecorationImage(
                              image:  FileImage(_image),
                              fit: BoxFit.cover,
                          ),                              
                        ),
                      ),
                ),

                Center(
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(20.0),
                    child: Container(
                      color: Colors.black26,
                      child: Icon(Icons.camera_alt,
                        color: Colors.white,
                        size: 40,
                      ),
                    ),
                  ),
                ),
               ,
            )
        ),
      ),
    );
  }

  @override
  userImage(File _image) async{
     setState(() {
      this._image = _image;
    });
  }
} 

目前,只要用户通过社交媒体登录获得新头像,Consumers 就会在整个应用程序中正确更新头像。新头像上传到服务器并通知ChangeNotifier。这里 Provider 的代码是 ;

Future<void> postSocialData(String avatar) async {
    final url = "http://example.com/example.php&currentavatar=" + $avatar;
    final response = await http.get(url);

    if (response.statusCode == 200) {
      currentavatar = "http://example.com/user.jpg";      
      var box = await Hive.openBox('currentuser');
      box.put('currentavatar', "http://example.com/user.jpg",);
      notifyListeners();    
    } 
  }

所以我尝试将它放入我的 Provider 并从图像选择器构建中的 onTap 函数调用它。这是 onTap 函数;

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

                  child: roundedButton(
                      "Gallery",
                      EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
                      const Color(0xFF167F67),
                      const Color(0xFFFFFFFF)),
                ),

这是它调用的 Provider

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

但这并没有让消费者了解新头像。我猜是因为头像的外部 url 没有改变,因为照片只是被替换并保持相同的名称。

使用 Hive 的侦听器是个好主意。但这并没有帮助,因为事实证明上传的图像 - 与替换图像具有相同的 URL - 没有在 server-side 上刷新。所以必须在web服务器上对缓存进行整理。