如何更新 Storage 中的图片并刷新 Streambuilder 以显示新图片?

Posted

技术标签:

【中文标题】如何更新 Storage 中的图片并刷新 Streambuilder 以显示新图片?【英文标题】:How to update picture in Storage and refresh Streambuilder to show the new picture? 【发布时间】:2022-01-15 19:15:31 【问题描述】:

我面临在 Flutter 应用中更新个人资料图片的问题。我已经显示了当前登录用户的详细信息,如下所示:

        body: StreamBuilder<Object>(
            stream: FirebaseFirestore.instance
                .collection('users')
                .doc(loggedInUser)
                .snapshots(),
            builder: (context, snapshot) 
              if (!snapshot.hasData) 
                return Center(
                  child: CircularProgressIndicator(),
                );
               else if (snapshot.data != null) 
                final userData = snapshot.data as DocumentSnapshot;
                return Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Container(
                      decoration: BoxDecoration(
                        color: Colors.grey[200],
                      ),
                      width: MediaQuery.of(context).size.width / 1,
                      height: MediaQuery.of(context).size.width / 2.5,
                      child: CachedNetworkImage(
                        imageUrl: '$userData['image']',
                        imageBuilder: (context, imageProvider) => Container(
                          width: 120,
                          height: 120,
                          decoration: BoxDecoration(
                            image: DecorationImage(
                              fit: BoxFit.cover,
                              image: imageProvider,
                            ),
                          ),
                        ),
                        placeholder: (context, url) =>
                            Center(child: CircularProgressIndicator()),
                        errorWidget: (context, url, error) => Icon(Icons.error),
                      ),
                    ),
                    Container(
                      margin: EdgeInsets.symmetric(horizontal: 10),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: [
                          SizedBox(height: 40),
                          Row(
                            children: [
                              Padding(
                                padding: const EdgeInsets.only(left: 10),
                                child: Text("Name : ",
                                    style: TextStyle(
                                        fontSize: 18,
                                        color: Colors.black54,
                                        fontWeight: FontWeight.w500)),
                              ),
                              Padding(
                                padding: const EdgeInsets.fromLTRB(60, 0, 0, 0),
                                child: Text('$userData['fullName']',
                                    style: TextStyle(
                                        fontSize: 18,
                                        color: Colors.black54,
                                        fontWeight: FontWeight.w500)),
                              )
                            ],
                          ),
                          SizedBox(height: 20),
                        ],
                      ),
                    ),
                  ],
                );
               else
                return Text('null');
            )

为了在新的“编辑个人资料”页面中更新个人资料图片,我编写的代码是:

  postNewProfilePicture(String userid) async 
    final ref =
        FirebaseStorage.instance.ref().child('users').child(userid + '.jpg');

    await ref.putFile(newprofilePic!);
    String url = await ref.getDownloadURL();

    newUploadedProfilePic = url;
  
                        ElevatedButton(
                            style: ElevatedButton.styleFrom(
                                padding: EdgeInsets.symmetric(
                                    horizontal: 45, vertical: 10),
                                textStyle: TextStyle(
                                    fontWeight: FontWeight.w500,
                                    color: Colors.white,
                                    fontSize: 15)),
                            onPressed: () 
                              postNewProfilePicture(widget.id);
                              if (_formKey.currentState!.validate()) 
                                updateUser(widget.id, name, newUploadedProfilePic);
                              
                              Navigator.of(context).pop();
                            ,
                            child: Text(
                              'Update',
                              style: TextStyle(fontSize: 15),
                            ),
                          ),
  Future<void> updateUser(id, name, newimage) 
    return users
        .doc(id)
        .update(
          'fullName': name,
          'image': newimage
        )
        .then((value) => print('Success'))
        .catchError((error) => print('Error: $error'));
  

使用这些代码,上传的新图片的 url 有时会成功插入 Firestore,但有时只会收到 null。在成功的新个人资料图片的情况下,我的应用程序也只显示旧的个人资料图片。如何成功插入新图片并加载显示?

【问题讨论】:

【参考方案1】:

“更新”它是针对一个字段的。将 set 与选项 merge true 一起使用。

  Future<void> updateUser(id, name, newimage) 
    return users
        .doc(id)
        .set(
      'fullName': name,
      'image': newimage
    , SetOptions(merge: true))
        .then((value) => print('Success'))
        .catchError((error) => print('Error: $error'));
  

尝试添加模型 MyUser

@immutable
class MyUser 
  final String id;
  final String fullName;
  final String image;

  const MyUser(required this.id, required this.fullName, required this.image);

  Map<String, dynamic> toMap() 
    return 
      'id': id,
      'fullName': fullName,
      'image': image,
    ;
  

  factory MyUser.fromMap(Map<String, dynamic>? map) 
    if (map == null) 
      return const MyUser(id: "", fullName: "", image: "");
    

    return MyUser(
      id: map['id'] as String,
      fullName: map['fullName'] as String,
      image: map['image'] as String,
    );
  

然后在您的流构建器中获取您的图像,如下所示

StreamBuilder<MyUser>(
        stream: FirebaseFirestore.instance
            .collection('users')
            .doc(loggedInUser)
            .snapshots()
            .map((map) => MyUser.fromMap(map.data())),
        builder: (context, snapshot) 
          final myUser = snapshot.data;
          if(myUser == null)
            return const Center(
              child: CircularProgressIndicator(),
            );
          
          print(myUser.image);
          return Container();
        )

【讨论】:

我试过了,但我的图像最终为空。 我更新了我的答案。对你有帮助吗? @coderhelp 您能否确认答案是否有帮助?如果是的话,你能接受它来帮助社区吗?谢谢。

以上是关于如何更新 Storage 中的图片并刷新 Streambuilder 以显示新图片?的主要内容,如果未能解决你的问题,请参考以下文章

请教大家:使用sdwebimage下载图片完成后更新cell中的imageview如何动态更改行高

如何更新 Azure.Storage.Blob 中的元数据

如何连续刷新屏幕并实时更新[关闭]

如何更新/刷新 RecyclerView 中的特定项目

如何使用 Postman 获取 Azure AD 刷新令牌?

如何从 Node 中的图像 url 将图像上传到 Google Cloud Storage?