Last active
April 21, 2025 08:56
-
-
Save herveGuigoz/b53ac82ea0c8ded220cc63ac84d95096 to your computer and use it in GitHub Desktop.
Firebase image Provider
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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