Home > Back-end >  Why is (list.length == otherList.length) showing false - Flutter
Why is (list.length == otherList.length) showing false - Flutter

Time:09-03

I have a List<File> imageFiles made up of files that a user selects and when they press submit, each of the files is uploaded to the collection in Firebase Storage. For each one, the downloadUrl is added to another list uploadedImages. I cannot upload the document to Firestore until all the downloadUrls are added to the uploadedImages list so I used an if statement if (imageFiles.length == uploadedImages.length) {<upload document>}. The problem is, in those lists are not the same length until the forEach block completes, and even then it doesn't return true. I confirmed that all the files are uploaded to Firebase Storage and printed the uploadedImages so I know they are eventually the same length but don't know how to make the if statement recognize that. Here is my current code:

List<String> uploadedUrls = [];

/// Uploads each file and adds its URL

    imageFiles.forEach((file) async {
      String fileName = '${UniqueKey()}_post.png';

      TaskSnapshot uploadTask = await FirebaseStorage.instance
          .ref()
          .child('/${user.uid}/posts/$postId/$fileName')
          .putFile(file);

      String url = await uploadTask.ref.getDownloadURL();

      setState(() {
        uploadedUrls.add(url);
      });
      print(uploadedUrls);
    });

/// Uploads post if all files and URLs are added *NOT WORKING*
 
    if (imageFiles.length == uploadedUrls.length) {
      Post post =
      Post(postId, uploadedUrls, user.uid, profile, location, Timestamp.now());

      try {
        FirebaseFirestore.instance
            .collection('users')
            .doc(user.uid)
            .collection('posts')
            .doc(postId)
            .set(post.toJson()).then((value) {
          setState(() {
            _isLoading = false;
          });
        });
      } on FirebaseAuthException {
        setState(() {
          _isLoading = false;
        });
      }
    }

CodePudding user response:

Because you are running an asynchronous function in forEach,it won’t wait until the task is completed. So you can either move the if condition inside the forEach’s callback below the setState or use a parent function as wrapper for both them, and it should await the first call

imageFiles.forEach((file) async {
      String fileName = '${UniqueKey()}_post.png';

      TaskSnapshot uploadTask = await FirebaseStorage.instance
          .ref()
          .child('/${user.uid}/posts/$postId/$fileName')
          .putFile(file);

      String url = await uploadTask.ref.getDownloadURL();

      setState(() {
        uploadedUrls.add(url);
      });
 
    if (imageFiles.length == uploadedUrls.length) {
       ....
 });

or extract the forEach loop into a async function

void addDownloafUrls() asyn {
   imageFiles.forEach((file) async { ... });
      
}

// And you can await this function


addDownloafUrls().then(() {
    if (imageFiles.length == uploadedUrls.length) {...}

})

  • Related