0

I have two process which both come with a loading time and therefore with separate LoadingIndicator Widgets:

  Future getImageURL(String? pictureUrl) async {
    if (pictureUrl == null) throw Exception('Image URL is null');
    try{
      final ref = storage.refFromURL(pictureUrl);
      final url = await ref.getDownloadURL().timeout(const Duration(seconds: 10));
      return url;
    } catch (e){
      log(e.toString());
      rethrow;
    }
  }

This Function is part of a FutureBuilder:

FutureBuilder(
      future: FireStorage().getImageURL(widget.imageUrl),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
          child: Image.network(
            snapshot.data, 
            loadingBuilder: (_, Widget child, ImageChunkEvent? loadingProgress) {
              if (loadingProgress == null) return child;
              return const Center(
                child: CircularProgressIndicator(color: Colors.white,),
              );
          );
        } else if (snapshot.hasError) {
          return Text("error);
        } else {
          return const Center(
            child: CircularProgressIndicator(color: Colors.white,)
          );
        }

So with this code I am displaying a LoadingIndicator until the url is fetched and then I am displaying another LoadingIndicator to get the Image from the Image.network().

The transition between the different LoadingIndicators is unfortunately not smooth. For a very short time no LoadingIndicator is displayed, which looks a little odd and unexpected. I tried wrapping both functions into one but obviously the Image.network() call is not an actual function but a named constructor.

Is there any way to do something like

await Image.network();

so I am sure that I just have an Image now which I could even pass as an argument?

Yuki
  • 255
  • 1
  • 2
  • 9

1 Answers1

0
  • You cannot await it like future because, Image.network() constructor is a widget not a function.
  • You can consider wrapping Image.network() widget in a FutureBuilder instead.

Update your function getImageWidget to:

Future<Widget> getImageWidget(String? pictureUrl) async {
  if (pictureUrl == null) throw Exception('Image URL is null');
  try {
    final ref = storage.refFromURL(pictureUrl);
    final url = await ref.getDownloadURL().timeout(const Duration(seconds: 10));
    return Image.network(
      url, 
      loadingBuilder: (_, Widget child, ImageChunkEvent? loadingProgress) {
        if (loadingProgress == null) return child;
        return const Center(
          child: CircularProgressIndicator(color: Colors.white,),
        );
      },
    );
  } catch (e){
    log(e.toString());
    rethrow;
  }
}

Use FurtureBuilder like:

FutureBuilder<Widget>(
  future: getImageWidget(widget.imageUrl),
  builder: (BuildContext context, AsyncSnapshot<Widget> snapshot) {
    if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
      return snapshot.data!;
    } else if (snapshot.hasError) {
      return Text("error);
    } else {
      return const Center(
        child: CircularProgressIndicator(color: Colors.white,)
      );
    }
  }
);

krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88