Flutter firebase setData() function assigns null value to a field before completion of an async function

145

Change this:

    storageReference.getDownloadURL().then((fileURL) {
      setState(() {
        _avatarUrl = fileURL;
        print('Print after async function completes...');
        print(_avatarUrl);

      });
    });

into this:

    var fileURL = await storageReference.getDownloadURL();
      setState(() {
        _avatarUrl = fileURL;
        print('Print after async function completes...');
        print(_avatarUrl);

      });
    });

Use await instead of then(). Currently you are entering the method uploadFile(), but since getDownloadURL() is asynchronous then the print() method is getting executed even before getting the url.

Share:
145
Bright
Author by

Bright

Updated on December 22, 2022

Comments

  • Bright
    Bright over 1 year

    I am trying to upload an avatar for a user to firestore storage and return the image url to save it against users avatarUrl property on the user instance. I am able to upload the image to firestore successfully. the issue comes with the receiving back of the url. The async function delays and hence the preceding user instanciation function proceeds with a null value for the avatarUrl property.

    Here is the function initiation

                        if(_formKey.currentState.validate()){
                          setState(() {
                            loading=true;
                          });
                          await uploadFile();
                          print('Print before async function complete...');
                          print(_avatarUrl);
                          dynamic result=  await SellerDatabaseService(uid:user.uid).sellerProfileSetup(
                            shopName: shopName,
                            phone: phone,
                            bio: bio,
                            location: location,
                            avatarUrl: _avatarUrl,
                            rating: 0,
                            sales: 0,
                            credit: 0,
                            posts: 0,
                            joinedDate:DateTime.now(),
                            //todo remove null from profile image
                          );
                          if(result==null){
                            setState(() {
                              loading=false;
                              error='Please supply correct details';
                            });
                          }
                        }
                      },
    

    Here is the upload function

     String _avatarUrl;
      Future uploadFile() async {
        StorageReference storageReference = FirebaseStorage.instance
            .ref()
            .child('avatars/${_image.path}');
        StorageUploadTask uploadTask = storageReference.putFile(_image);
        await uploadTask.onComplete;
        print('File Uploaded');
        storageReference.getDownloadURL().then((fileURL) {
          setState(() {
            _avatarUrl = fileURL;
            print('Print after async function completes...');
            print(_avatarUrl);
    
          });
        });
      }
    

    This is the output

    I/flutter ( 7332): Print before async function complete...
    I/flutter ( 7332): null
    I/flutter ( 7332): Print after async function completes...
    I/flutter ( 7332): https://firebasestorage.googleapis.com/v0/b/sakahapa-77a09.appspot.com/o/avatars%2Fdata%2Fuser%2F0%2Fcom.sakahapa.sakaHapa%2Fcache%2Fimage_picker246664303.jpg?alt=media&token=5868d6a5-b1e3-4aa2-8e64-72dc6e9b0a0f
    

    As seen there the url returns later after the SellerDatabaseService(uid:user.uid).sellerProfileSetup() function has run. So i get a null value on the avatarUrl property. How do i prevent this? Thanks in advance.