Flutter Firebase - 在 Firestore 上更改图像时更新用户个人资料图像 returns 出错

Flutter Firebase - updating user profile image returns an error while the image change on Firestore

我有一个带有个人资料页面的应用程序,我想在其中有一张个人资料图片,用户可以随时更新。

我现在拥有的代码执行以下操作:StreamBuilder 将获取包含当前用户 UID 的 Firestore 集合,并构建一个 Image.network 获取文档“URL”来自 snapshot.data.

问题:

第一次,当用户创建新用户时,我在图像上有一个占位符,当用户从图库中选择新图像时,它会 return 更新之间的时间错误收集并更新 UI,然后更改为新图像。此外,更改图像需要花费大量时间,具体取决于图像的大小。

如果有人可以给我一些不同的方法来了解我的工作方式,我将不胜感激。

上传到Firestore的函数:

File _image;

  Future getImage(bool gallery) async {
    ImagePicker picker = ImagePicker();
    PickedFile pickedFile;
    // Let user select photo from gallery
    if (gallery) {
      pickedFile = await picker.getImage(
        source: ImageSource.gallery,
      );
    }
    setState(() {
      if (pickedFile != null) {
        _image = File(pickedFile.path);
        uploadFile(_image);
        uploadToFirebase(); // Use if you only need a single picture
      } else {
        print('No image selected.');
      }
    });
  }

  Future<String> uploadFile(File image) async {
    String downloadURL;
    Reference ref = FirebaseStorage.instance
        .ref()
        .child("images/${_firebaseAuth.currentUser.uid}");
    await ref.putFile(image);
    downloadURL = await ref.getDownloadURL();
    return downloadURL;
  }

  Future uploadToFirebase() async {
    final CollectionReference users =
        _firebaseFirestore.collection("Companies");
    final String uid = _firebaseAuth.currentUser.uid;

    String url = await uploadFile(
        _image); // this will upload the file and store url in the variable 'url'
    await users.doc(uid).update({'url': url});
    final result = await users.doc(uid).get();
    return result.data()["url"];
  }

我显示图片的代码:

Container(
                                child: _image != null
                                    ? Column(
                                        children: [
                                          StreamBuilder(
                                            stream: _firebaseFirestore
                                                .collection("Companies")
                                                .doc(_firebaseAuth
                                                    .currentUser.uid)
                                                .snapshots(),
                                            builder: (BuildContext context,
                                                AsyncSnapshot snapshot) {
                                              if (snapshot.connectionState ==
                                                  ConnectionState.waiting) {
                                                return Text("Loading");
                                              }
                                              return Image.network(
                                                snapshot.data.data()["url"],
                                                width: 100,
                                                height: 100,
                                              );
                                            },
                                          ),
                                        ],
                                      )
                                    : Container(
                                        decoration: BoxDecoration(
                                          color: Colors.grey[200],
                                          borderRadius:
                                              BorderRadius.circular(50),
                                        ),
                                        width: 100,
                                        height: 100,
                                        child: Icon(
                                          Icons.camera_alt,
                                          color: Colors.grey[800],
                                        ),
                                      ),
                              ),

首先,在您的代码中,您上传文件两次:一次在 setState() 中,另一次在 uploadToFirebase() 中;

当 snapshot.connectionState 与 connectionState.done 不同时,您可以尝试显示加载文本:

if (!snapshot.hasData) {
    return Text("Loading");
}

return Image.network(
    snapshot.data.data()["url"],
    width: 100,
    height: 100,
);

编辑:你能告诉我这是否有效吗?

File _image;
bool _loading = false;
final FirebaseStorage _storage = FirebaseStorage(storageBucket:'gs://LINK.com'); //find your link in your storage console like this screenshot https://i.imgur.com/gW35HJk.png
StorageUploadTask _uploadTask;

  Future getImage(bool gallery) async {
    this.setState((){
    _loading = true;
    });
    ImagePicker picker = ImagePicker();
    PickedFile pickedFile;
    // Let user select photo from gallery
    if (gallery) {
      pickedFile = await picker.getImage(
        source: ImageSource.gallery,
      );
    }
    setState(() {
      if (pickedFile != null) {
        _image = File(pickedFile.path);
        uploadFile(_image);
      } else {
        print('No image selected.');
        this.setState((){
        _loading = false;
        });

      }
    });
  }

  Future<String> uploadFile(File image) async {
    String downloadURL;
    String filePath = "images/${_firebaseAuth.currentUser.uid}";
    setState(() {
      _uploadTask = _storage.ref().child(filePath).putFile(image).onComplete;
    });
    var imageUrl = await (await 
    _uploadTask.onComplete).ref.getDownloadURL();
    downloadURL = imageUrl.toString();
    
    uploadToFirebase(downloadURL);
  }

  Future uploadToFirebase(downloadURL) async {
    final CollectionReference users =
        _firebaseFirestore.collection("Companies");
    final String uid = _firebaseAuth.currentUser.uid;

    String url = downloadURL // this will upload the file and store url in the variable 'url'
    await users.doc(uid).update({'url': url});
    final result = await users.doc(uid).get();

    if (result != null) {
       setState((){
            getImage().onComplete{
            loading = false;
       }
       return result.data()["url"];
    }
    });
  }

----------Below is before edit---------------

Use a bool to determine if loading is complete or not

bool _loading = false;

    Future getImage(bool gallery) async {
        this.setState((){
        _loading = true;
        });
    
        ImagePicker picker = ImagePicker();
        PickedFile pickedFile;
        // Let user select photo from gallery
        if (gallery) {
          pickedFile = await picker.getImage(
            source: ImageSource.gallery,
          );
        }
        setState(() {
          if (pickedFile != null) {
            _image = File(pickedFile.path);
            uploadFile(_image);
            uploadToFirebase(); // Use if you only need a single picture'
     setState(() {
          _loading = false;
        });
          } else {
            print('No image selected.');
            setState(() {
          _loading = false;
        });
          }
        });
      }