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.
MemoryImage
AssetImage
FileImage
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 tofalse
.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 oncolorBlendMode
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 ofTextDirection
to paint the image. Defaults tofalse
.bool gaplessPlayback
: Whether to continue showing the old image when the image provider changes. Defaults tofalse
.FilterQuality filterQuality
: TheFilterQuality
of the image. Defaults toFilterQuality.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.