[Flutter/Dart] Different view while waiting for image acquisition
- M.R 
- Jul 16, 2023
- 2 min read
Things to do
- There is a widget that displays an image 
- Images are acquired from remote storage 
- Because it takes time, I would like to display notification that it is waiting during that time. 
Solution
Switch views in FutureBuilder.
FutureBuilder<ImageProvider>(
  future: getImage(),  
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    }
    if ((snapshot.hasError) || (!snapshot.hasData)){
      //Error handling
    }
    return Container(
      width: 100,
      height: 100,
      decoration: BoxDecoration(
        borderRadius: const 
        BorderRadius.all(Radius.circular(10)),
        image: DecorationImage(
          fit: BoxFit.contain,
          image: snapshot.data!
        ),
      )
    );
  }
)Future<ImageProvider> getImage()async{
  //method to get image from remote storage
}Common processing for different image sources
In the above, we considered remote storage as the source of the image, but it can be a local file or an image file in an asset. How can we standardize the processing for these different sources?
Let's create a polymorphic class like this:
- Creating an abstract class ImageSource class 
- Define Future <ImageProvider> getImage() 
- Define concrete classes LocalImage and RemoteImage that inherit the ImageSource class, and add implementations of getImage for each 
- The image display widget takes an ImageSource instance as an argument and calls getImage() to get an ImageProvider 
abstract class ImageSource{
  String path;  //image file path 
  Future<ImageProvider> getImage(); 
}
//Local image file
class LocalImage extends ImageSource{
  @override
  Future<ImageProvider> getImage()async{
    return FileImage(File(path));
  }
}
//Remote storage file
class RemoteImage extends ImageSource{
  @override
  Future<ImageProvider> getImage()async{
    String _downloadPath = await _downLoadFile();  
    return NetworkImage(_downloadPath);
  }
}
Widget ImageWidget(ImageSource imgSrc){
  return FutureBuilder<ImageProvider>(
    future: imgSrc.getImage(),  
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return CircularProgressIndicator();
      }
      if ((snapshot.hasError) || (!snapshot.hasData)){
        //Error handling
      }
      return Container(
        width: 100,
        height: 100,
        decoration: BoxDecoration(
          borderRadius: const 
          BorderRadius.all(Radius.circular(10)),
          image: DecorationImage(
            fit: BoxFit.contain,
            image: snapshot.data!
          ),
        )
      );
    }
  )
}For LocalImage, getImage() doesn't need to be async, but it's async for convenience with RemoteImage.
(Only the image is displayed with almost no waiting)






Comments