Introduction to Image in Flutter

3 min read, 21 November, 2018

Images are used extensively in mobile apps. Flutter provides four different ways to use images.

  • Load images from remote servers.
  • Load images from assets.
  • Load images from file system.
  • Create images from binary data.

This article only covers the first two usage scenarios.

Load images from remote servers

This is the most straightforward usage scenario of images. Images are stored on remote servers. We simply load images by URLs. Image.network creates a widget to display an image loaded by a URL. The argument src specifies the image URL.

For example, Image.network('https://picsum.photos/300?random') creates a new widget with image loaded from given URL.

Custom headers

If custom headers are required to get the image, the argument headers of type Map<String, String> can be used. A typical example is to access protected images which require custom authentication headers.

For example, the code below adds the custom Authentication when requesting the image.

Image.network(
  'https://picsum.photos/300?random',
  headers: {
    'Authentication': 'Basic xxxxx',
  },
)

Image caching

All images downloaded using Image.network are cached regardless of HTTP response headers. This means that as long as the image URL doesn't change, the image won't be refreshed even though its content may be changed in the remote server. You can use a cache-buster to force downloading of images.

Load images from assets

Some images, e.g. logos and icons, can be bundled as assets with the app. Image.asset creates a widget to display an image loaded by its name in the asset bundle.

In the file pubspec.yaml, it declares an asset image in the path assets/images/sample.png.

flutter:
  assets:
    - assets/images/sample.png

This image can be loaded using Image.asset('assets/images/sample.png').

Display images

When using image widgets, we should specify their size using either height or width arguments, or place image widgets in contexts that set tight layout constraints. This makes sure that the layout doesn't change when the image is loading. Otherwise, the image may appear to take no space first, then expand to its actual size. It looks like other widgets are pushed away by the image.

For example, if you want to display a list of items with thumbnail images displayed at the left side and content displayed at the right side. You should assign fixed size to the images, and make the content take the remaining space. By doing this, the content remains in the same size and position when the image is loading.

The code sample from Introduction to ListView in Flutter demonstrates this usage pattern. Image size is fixed by using the arguments width and height. The Text widget takes the remaining space by using a Expanded widget.

Widget _generateItem(int index) {
  log.info('Generate item $index');
  return new Container(
    padding: const EdgeInsets.all(8.0),
    child: new Row(
      children: <Widget>[
        new Image.network(
          'http://via.placeholder.com/200x100?text=Item$index',
          width: 200.0,
          height: 100.0,
        ),
        new Expanded(child: new Text('Item $index'))
      ],
    ),
  );
}

Below is the screenshot of using images.

Screenshot of Image

Source code

Source code of this article is available on GitHub.