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

How to update picture in Storage and refresh Streambuilder to show the new picture?

我在 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。在新个人资料图片成功的情况下,我的应用程序也只显示旧个人资料图片。如何才能成功插入新图片并加载显示?

“更新”是针对一个字段的。将 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();
        })