Loading and Optimizing Images
1. Using AssetBundle for Loading Assets
| Property | Description | Usage |
|---|---|---|
| load | Loads an asset from the bundle asynchronously | ByteData data = await rootBundle.load('assets/images/example.png'); |
| loadString | Loads an asset as a string | String content = await rootBundle.loadString('assets/data/config.json'); |
| loadImage | Loads an image asset and returns a Future<Image> | Future<Image> image = rootBundle.loadImage('assets/images/logo.png'); |
Example: Loading an Image Asset
import 'package:flutter/material.dart';
import 'dart:io';
class AssetImageLoader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Asset Image Example")),
body: Center(
child: Image.asset(
'assets/images/flutter_logo.png',
width: 200,
height: 200,
),
),
);
}
}
Note: Ensure that the asset path is correctly declared in
pubspec.yaml under the flutter: section.
Warning: Using
Image.asset with large images can cause memory issues. Consider using Image.memory or image optimization techniques.
2. Implementing Precaching
Example: Using cached_network_image
// pubspec.yaml
dependencies:
cached_network_image: ^3.4.1
// Dart code
import 'package:cached_network_image/cached_network_image.dart';
CachedNetworkImage(
imageUrl: "https://example.com/image.jpg",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
| Property | Description | Values |
|---|---|---|
| imageUrl | URL of the image to load | String |
| placeholder | Widget to show while image is loading | WidgetBuilder |
| errorWidget | Widget to show if image fails to load | WidgetBuilder |
Note:
cached_network_image automatically handles image caching and precaching.
Example: Manual Image Caching
// Using Image.memory with precached bytes
import 'dart:io';
import 'package:flutter/material.dart';
Future<Uint8List> precacheImage(String url) async {
final response = await HttpClient().getUrl(Uri.parse(url)).close();
return Uint8List.fromList(response.cast<int>().toListSync());
}
// Usage in widget
FutureBuilder<Uint8List>(
future: precacheImage("https://example.com/image.jpg"),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Image.memory(snapshot.data!);
} else {
return CircularProgressIndicator();
}
},
)
3. Using cacheWidth and cacheHeight
| Property | Description | Values | Notes |
|---|---|---|---|
| cacheWidth | Defines the width to be used for caching the image | double |
Used in conjunction with cacheHeight to optimize image caching |
| cacheHeight | Defines the height to be used for caching the image | double |
Used in conjunction with cacheWidth to optimize image caching |
Example: Using cacheWidth and cacheHeight
Image.asset(
'assets/images/example.png',
cacheWidth: 200,
cacheHeight: 150,
)
Note: Setting
cacheWidth and cacheHeight can significantly improve performance when displaying the same image at different sizes by pre-scaling and caching the image at the specified dimensions.
4. Loading Images from Multiple Sources
| Source Type | Description | Code Example | Notes |
|---|---|---|---|
| Asset Image | Images bundled with the app using pubspec.yaml |
Image.asset('assets/images/flutter_logo.png') |
Best for static images included in the app bundle |
| Network Image | Images loaded from a URL over the internet | Image.network('https://example.com/image.jpg') |
Use ImageProvider for advanced control |
| File Image | Images from local file system paths | Image.file(File('/path/to/image.png')) |
Requires proper file permissions on mobile platforms |
| Memory Image | Images loaded from memory (e.g., Uint8List) |
Image.memory(bytes) |
Useful for dynamically generated or downloaded images |
Network vs Asset Image Loading
- Network: Slower due to network latency; supports caching
- Asset: Faster load times; bundled with app, no network dependency
Note: Always provide a fallback image using
errorBuilder or loadingBuilder for better UX.
5. Using Image Formats
| Format | Support | Notes |
|---|---|---|
| PNG | Good | Lossless compression, supports transparency |
| JPG/JPEG | Good | Lossy compression, good for photos |
| GIF | Good | Supports animation and transparency |
| WebP | Good | Modern format with better compression than JPG/PNG |
| BMP | Limited | Uncompressed, large file sizes |
| SVG | Modern | Vector format, scalable without loss |
Note: WebP format is supported on Android and iOS but requires additional setup for web.
Warning: Large image files can cause performance issues. Consider using
MemoryImage or FileImage for optimized loading.
6. Loading SVG Images
Flutter provides built-in support for loading SVG images using the flutter_svg package. SVGs are vector graphics that scale well and are lightweight.
| Property | Description | Values |
|---|---|---|
| SvgPicture.asset | Loads an SVG from the assets folder. | String assetPath |
| SvgPicture.network | Loads an SVG from a network URL. | String url |
| SvgPicture.string | Loads an SVG from a string. | String svgString |
Example: Loading SVG from Assets
<SvgPicture.asset(
'assets/images/logo.svg',
width: 100,
height: 100,
)>
Example: Loading SVG from Network
<SvgPicture.network(
'https://example.com/image.svg',
width: 200,
height: 200,
)>
Note: Ensure that SVG files are added to
pubspec.yaml under the flutter: section in the assets list.
Warning: Large SVGs may cause performance issues. Consider optimizing SVGs using tools like
svgo.
| Property | Default | Description |
|---|---|---|
| width | null |
Width of the SVG image. |
| height | null |
Height of the SVG image. |
| fit | BoxFit.contain |
How the SVG should be inscribed into the allowed space. |
| alignment | Alignment.center |
How to align the SVG within its container. |
7. Using Lottie Animations
Lottie animations are lightweight, scalable vector animations that can be used in Flutter applications. They are rendered using the lottie package.
| Property | Description | Values |
|---|---|---|
| asset | Path to the Lottie JSON file in the assets folder | 'assets/animations/example.json' |
| animation | Direct reference to an Animation object (alternative to asset) | Animation<LottieAsset> |
| width | Width of the animation | double |
| height | Height of the animation | double |
| fit | How the animation should be fitted to its container | BoxFit values (e.g., BoxFit.contain) |
| loop | Whether the animation should loop | true or false |
| animate | Whether the animation should play automatically | true or false |
Example: Basic Lottie Animation
import 'package:lottie/lottie.dart';
Lottie.asset(
'assets/animations/example.json',
width: 200,
height: 200,
fit: BoxFit.contain,
loop: true,
)
Example: Lottie Animation with Custom Controller
import 'package:lottie/lottie.dart';
final controller = AnimationController(vsync: this, duration: Duration(seconds: 5));
Lottie.asset(
'assets/animations/example.json',
controller: controller,
animate: false, // Manually control animation
)
Note: Ensure that the Lottie JSON file is added to your
pubspec.yaml under the assets section.
Warning: Large Lottie files can impact performance. Consider optimizing animations using tools like Lottie Optimizer.
8. Implementing Progressive Image Loading
Progressive image loading enhances user experience by displaying a low-quality version of an image first, followed by the full-resolution image. This technique is particularly useful for mobile devices with limited bandwidth.
| Property | Description | Default Value | Notes |
|---|---|---|---|
| fit | Defines how the image should be inscribed into the space allocated for it. | BoxFit.cover |
Controls aspect ratio and positioning. |
| alignment | Defines how the image should be aligned within its container. | Alignment.center |
Useful for centering or aligning images in specific positions. |
| repeat | Defines how the image should be repeated if it's smaller than its container. | ImageRepeat.noRepeat |
Applies to background or pattern-like images. |
Example: Using Image.asset with Progressive Loading
Image.asset(
'assets/images/progressive_image.jpg',
fit: BoxFit.cover,
alignment: Alignment.center,
repeat: ImageRepeat.noRepeat,
)
Note: For true progressive loading, consider using packages like
flutter_blurhash or cached_network_image to display a blurred placeholder while the full image loads.
Progressive Image Loading Best Practices
- Use
Image.memoryorImage.filefor better control over image data. - Implement a
loadingBuilderfor custom loading states. - Preload images in the background to improve perceived performance.
9. Using Resolution-Aware Images
Flutter supports resolution-aware images to ensure optimal display on different device pixel densities. The framework automatically selects the most appropriate image asset based on the device's devicePixelRatio.
| Asset Folder | Image Name | Pixel Density | Description |
|---|---|---|---|
lib/assets/images/ |
logo.png |
1.0x |
Default image for low-density screens |
lib/assets/images/ |
logo@2x.png |
2.0x |
Image for medium-density screens (e.g., HDPI) |
lib/assets/images/ |
logo@3x.png |
3.0x |
Image for high-density screens (e.g., XHDPI) |
Example: Loading Resolution-Aware Image
Image.asset(
'lib/assets/images/logo.png',
fit: BoxFit.contain,
)
Note: Flutter uses
@2x and @3x suffixes to denote image resolutions. The framework will automatically select the best image based on the device's pixel density.
10. Optimizing Image Performance
| Optimization Technique | Description | Implementation | Notes |
|---|---|---|---|
| Image caching | Reusing previously loaded images to reduce network requests and improve load times. | MemoryImage(imageBytes) |
Use AssetImage or NetworkImage with caching enabled. |
| Image compression | Reducing image file size without significant loss in visual quality. | Image.asset('assets/image.jpg', fit: BoxFit.contain) |
Compress images using tools like ImageOptim or TinyPNG before adding to assets. |
| Lazy loading | Loading images only when they are visible on screen. | ListView.builder( ... itemBuilder: (context, index) { return Image.network(urls[index]); }) |
Use ListView.builder or GridView.builder to load images on demand. |
| Image resizing | Scaling images to the exact size needed for display to avoid unnecessary memory usage. | Image.asset('assets/image.png', width: 100, height: 100) |
Use width and height properties to scale images. |
Example: Using CachedNetworkImage for Performance
import 'package:cached_network_image/cached_network_image.dart';
CachedNetworkImage(
imageUrl: 'https://example.com/image.jpg',
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
Note: Flutter's default image loading does not cache images by default. Use
CachedNetworkImage or similar packages to implement caching.
Warning: Large images can cause memory issues and UI lag. Always ensure image sizes are optimized for the target device screen.