Skip to content

Instantly share code, notes, and snippets.

@herveGuigoz
Last active April 21, 2025 08:56
Show Gist options
  • Save herveGuigoz/b53ac82ea0c8ded220cc63ac84d95096 to your computer and use it in GitHub Desktop.
Save herveGuigoz/b53ac82ea0c8ded220cc63ac84d95096 to your computer and use it in GitHub Desktop.
Firebase image Provider
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:async';
import 'dart:ui' as ui;
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
/// An [ImageProvider] that retrieves an image from Firebase Storage.
@immutable
class FirebaseImageProvider extends ImageProvider<FirebaseImageProvider> {
FirebaseImageProvider(this.name, {this.bucket, this.scale = 1.0}) : _storage = FirebaseStorage.instance.ref(bucket);
/// Firebase storage reference
final Reference _storage;
/// Asset name
final String name;
/// Bucket name
final String? bucket;
/// Scale of the image
final double scale;
@override
Future<FirebaseImageProvider> obtainKey(ImageConfiguration configuration) {
return SynchronousFuture<FirebaseImageProvider>(this);
}
@override
ImageStreamCompleter loadImage(FirebaseImageProvider key, ImageDecoderCallback decode) {
final chunkEvents = StreamController<ImageChunkEvent>();
return MultiFrameImageStreamCompleter(
codec: _loadAsync(key, chunkEvents, decode: decode),
chunkEvents: chunkEvents.stream,
scale: key.scale,
debugLabel: name,
informationCollector:
() => <DiagnosticsNode>[
DiagnosticsProperty<FirebaseImageProvider>('Image provider', this),
DiagnosticsProperty<FirebaseImageProvider>('Image key', key),
],
);
}
Future<ui.Codec> _loadAsync(
FirebaseImageProvider key,
StreamController<ImageChunkEvent> chunkEvents, {
required ImageDecoderCallback decode,
}) async {
try {
final image = await _storage.child(key.name).getData();
if (image == null) {
throw FirebasekImageLoadException(key.name);
}
return decode(await ui.ImmutableBuffer.fromUint8List(image));
} on FirebaseException catch (error, stackTrace) {
Error.throwWithStackTrace(
FirebasekImageLoadException('Failed to load ${key.name} in bucket $bucket', error: error),
stackTrace,
);
}
}
@override
bool operator ==(covariant FirebaseImageProvider other) {
if (identical(this, other)) return true;
return other.name == name && other.scale == scale;
}
@override
int get hashCode => name.hashCode ^ scale.hashCode;
}
class FirebasekImageLoadException implements Exception {
FirebasekImageLoadException(this.name, {this.error});
final String name;
Object? error;
@override
String toString() => 'FirebaseImageLoadException: Failed to load image $name';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment