Search code examples
flutterfutureflutter-futurebuilder

Trying to handle exception in a Future<String?> with no success in a `FutureBuilder` context


I have to fetch ta video URL store in FireStore before displaying the video itself. I used a FutureBuilderin my build to do so:

if (ad.videoUrl != null)
              FutureBuilder(
                  future: Video.videoUrl("blabla"), //ad.videoUrl!),
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      final url = snapshot.data;
                      return Text(url ?? "No video found");
                    } else {
                      return Row(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          children: const [
                            Text("Searching the video on the cloud"),
                            CircularProgressIndicator()
                          ]);
                    }
                  }),

The future itself is straightforward:

 /// Fetches the video url from the video [name]
  static Future<String?> videoUrl(String name) {
    final videoBucket =
        FirebaseStorage.instanceFor(bucket: Globals.storageBucketUrl);

    final videoBucketRef = videoBucket.ref();

    final item = videoBucketRef.child(name);

    return item.getDownloadURL();
  }

And like this, I've got what I want. Perfect.

But now, I want to handle the exception within the future so that it returns null when any occur.

I've updated my code as follows:

 /// Fetches the video url from the video [name]
  static Future<String?> videoUrl(String name) async {
    final videoBucket =
        FirebaseStorage.instanceFor(bucket: Globals.storageBucketUrl);

    final videoBucketRef = videoBucket.ref();
    try {
      final item = videoBucketRef.child(name);

      return await item.getDownloadURL();
    } catch (e) {
      return null;
    }

Though the exception is caught as expected (when I fetch a video name that does not exist), it looks like the future never returns a value (neither null or the URL when it exists.

Therefore what's wrong in my code?

Note: Btw, I have also tried this without success when the exception occurs, though it is ok for an existing video name.

/// Fetches the video url from the video [name]
  static Future<String?> videoUrl(String name) async {
    final videoBucket =
        FirebaseStorage.instanceFor(bucket: Globals.storageBucketUrl);

    final videoBucketRef = videoBucket.ref();
    try {
      final item = videoBucketRef.child(name);

      final url = await item.getDownloadURL();
      return Future<String?>.value(name);
    } catch (e) {
      return Future<String?>.value(null);
    }

Solution

  • instead of returning null, you can throw an exception like this:

    catch (e) {
     throw Exception("some error here");
    }
    

    inside the FutureBuilder you can use the hasError to show some widget based on it:

    FutureBuilder(
                      future: Video.videoUrl("blabla"), //ad.videoUrl!),
                      builder: (context, snapshot) {
                        if (snapshot.hasData) {
                          final url = snapshot.data;
                          return Text(url ?? "No video found");
                        } else if(snapshot.hasError) {
                          return Text("error ${snapshot.error}");
                         } else{
                          return Row(
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                              children: const [
                                Text("Searching the video on the cloud"),
                                CircularProgressIndicator()
                              ]);
                        }
                      }),