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

Posted

技术标签:

【中文标题】Flutter/Dart - 如何在其他屏幕上的图像选择器后更新图像【英文标题】:Flutter/Dart - How to update Image after Image Picker on other Screens 【发布时间】:2021-01-22 05:01:37 【问题描述】:

我正在使用 Flutter 的 Image Picker 插件以允许用户更改他们的头像。当他们转到他们的帐户页面时,他们会看到他们的常规头像照片,顶部带有相机图标。单击相机图标将允许他们从相机中拍照或从他们的图库中选择新头像。选择新的后,头像照片会自动更新。但是,当离开他们的帐户页面时,旧头像在应用程序的其余部分都可见。我将ProviderChange NotifierConsumers 一起用于其他地方的头像。但问题是我只能在构建中访问Provider,所以我不知道在我的代码中我可以在哪里调用Provider。除此之外,我在应用程序中使用的 Avatar 来自一个互联网 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 会在用户通过社交媒体登录获得新头像时正确更新整个应用程序中的头像。新头像上传到服务器并通知ChangeNotifierProvider 这里的代码是 ;

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 并从 Image Picker 构建中的 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();
   

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

【问题讨论】:

提供者模型的代码在哪里? 由于您将选定的头像放在 Hive Box 中,因此您可以在任何需要图像的地方调用框引用上的 get 如果你在某个地方调用openBox,比如main,那么在应用程序的其余部分,你可以使用box方法来检索盒子。 box() 是同步调用。 同步开箱需要Hive.box('boxName') Hive 有一个ValueListenableBuilder 【参考方案1】:

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

【讨论】:

以上是关于Flutter/Dart - 如何在其他屏幕上的图像选择器后更新图像的主要内容,如果未能解决你的问题,请参考以下文章

从原生 Android 主屏幕小部件调用 Flutter (Dart) 代码

如何在颤动的主页中导航屏幕?

如何从 Flutter(Dart) 中的另一个类调用方法?

如何在 Flutter/Dart 中将 Future<double> 转换为 double?

flutter Dart语言List如何获取索引值

如何在视频/图像上添加图像或文本(水印) - Flutter/Dart