Flutter - Using MemoryImage Examples

This tutorial shows you how to use MemoryImage in Flutter, including how to convert an image into the required data type.

Flutter has some ImageProvider implementations, one of which is MemoryImage, which is used to load raw image from memory. With the image data already in the memory, this is the fastest kind of ImageProvider. Below is the list of Flutter's ImgaeProvider from the fastest to the slowest.

  1. MemoryImage
  2. AssetImage
  3. FileImage
  4. NetworkImage

Using MemoryImage Constructor

The constructor of MemoryImage image only has one required parameter: bytes whose type is Unit8List. It contains the bytes to be decoded into an image. The other, which is optional, is a double named scale, used the scale the size of the image.

  MemoryImage(this.bytes, { this.scale = 1.0 })

Therefore, you need to have the image data as Unit8List bytes. To convert an image into Unit8List, you can make use of Flutter's AssetBundle. The usage of AssetBundle depends on where the image comes from.

If the image is from assets, you can do it like in the below example.

  Uint8List data = (await rootBundle.load('assets/images/pikachu.png'))
          .buffer
          .asUint8List();

The code above load the asset image using AssetBundle's load method to get Future<ByteData>. Then, use buffer property to get the ByteBuffer which has asUint8List method for getting the appropriate data type that can be passed to the constructor.

If the image is from network, you can convert it into Uint8List in a similar way, but you need to use NetworkAssetBundle, which extends AssetBundle.

  Uint8List data = (await NetworkAssetBundle(Uri.parse('https://www.woolha.com'))
      .load("/media/2019/06/buneary.avif")
  )
      .buffer
      .asUint8List();

After having the required data type, it's very easy to construct a MemoryImage. Just call the constructor with the data as the first parameter. Optionally, you can also pass optional parameter scale.

  MemoryImage(imageData, scale: 2))

Below is a simple app that uses MemoryImage

  import 'dart:typed_data';
  
  import 'package:flutter/material.dart';
  import 'package:flutter/services.dart';
  
  void main() => runApp(MyApp());
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Welcome to Flutter',
        home: MemoryImageApp(),
      );
    }
  }
  
  class MemoryImageApp extends StatefulWidget {
    @override
    _MemoryImageExampleState createState() {
      return _MemoryImageExampleState();
    }
  }
  
  class _MemoryImageExampleState extends State {
    Uint8List imageData;
  
    @override
    void initState() {
      super.initState();
      loadAsset();
    }
  
    void loadAsset() async {
      Uint8List data = (await rootBundle.load('assets/images/pikachu.png'))
          .buffer
          .asUint8List();
      setState(() => this.imageData = data);
    }
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Woolha.com - Flutter Tutorial'),
        ),
        body: Center(child: _ImageWrapper()),
      );
    }
  
    Widget _ImageWrapper() {
      if (imageData == null) {
        return CircularProgressIndicator();
      }
  
      return Container(
        width: 150,
        height: 150,
        decoration: BoxDecoration(
          image: new DecorationImage(
              fit: BoxFit.cover, image: MemoryImage(imageData, scale: 0.5)),
        ),
      );
    }
  }

First, it converts an image from asset into Uint8List, then store the result as a state variable. After that, the image data is used as the bytes property of MemoryImage. With the optional scale property set to 0.5, the image is scaled down.

Not only for BoxDecoration, it can also be used for any widget which has a property of type ImageProvider, such as Image and CircleImage

Using Image.Memory() Named Constructor

This is another way to create a MemoryImage which also requires a Uint8List data of the image.

Below is the basic usage of the named constructor

  image: new DecorationImage(
    fit: BoxFit.cover,
    image: Image.memory(imageData).image
  ),

There are plenty of available parameters you can pass in the constructor as shown below. The only required parameter is bytes.

  • Uint8List bytes* : The image data.
  • Key key: The widget key, used to control if it's should be replaced.
  • double scale: How to scale the image. Defaults to 1.0.
  • ImageFrameBuilder frameBuilder: A builder function responsible for creating the widget that represents this image..
  • String semanticLabel: Semantic description of the image.
  • bool excludeFromSemantics: Whether to exclude this image from semantics. Defaults to false.
  • double width: The height of the image.
  • double height: The height of the image.
  • Color color: The color to be blended with the image depending on colorBlendMode value.
  • BlendMode colorBlendMode: How to combine color with the image.
  • BoxFit fit: How to inscribe the image into the space allocated during layout.
  • AlignmentGeometry alignment: How to align the image within its bounds.
  • ImageRepeat repeat: How to paint any portions of the layout bounds not covered by the image.
  • Unit8List bytes*: The image data.
  • Rect centerSlice: The center slice for a nine-patch image.
  • bool matchTextDirection: Whether to use the value of TextDirection to paint the image. Defaults to false.
  • bool gaplessPlayback: Whether to continue showing the old image when the image provider changes. Defaults to false.
  • FilterQuality filterQuality: The FilterQuality of the image. Defaults to FilterQuality.low.
  • int cacheWidth: Indicates that the image must be decoded at specified width.
  • int cacheHeight: Indicates that the image must be decoded at specified height.

*: required

 

Whether using the MemoryImage constructor or the Image.Memory named constructor, you need to have the image data as Uint8List first. After that, just pass the data to the constructor to show the image.