如何以单独的方法获取 Flutter Firebase 存储?
Posted
技术标签:
【中文标题】如何以单独的方法获取 Flutter Firebase 存储?【英文标题】:How to get Flutter Firebase Storage in a separate method? 【发布时间】:2018-07-14 05:44:12 【问题描述】:我已成功将图像保存到我的 Firebase 存储参考中。现在我需要下载它。我见过的例子都是用同样的方法上传和下载,用同样的StorageUploadTask和这行代码...
final Uri downloadUrl = (await uploadTask.future).downloadUrl;
我的问题是如何从不需要 uploadTask.future
的单独方法获取 downloadUrl,因为我只是在 FirebaseUser 更新他们的个人资料图片时上传图片?
【问题讨论】:
【参考方案1】:StorageReference
现在有 Future<dynamic> getDownloadURL()
方法。将结果重新键入 String 并将其与您的 NetworkImage
小部件一起使用:
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
class FirestoreImage extends StatefulWidget
final StorageReference reference;
final Widget fallback;
final ImageProvider placeholder;
FirestoreImage(
Key key,
@required this.reference,
@required this.fallback,
@required this.placeholder);
@override
FirestoreImageState createState() =>
FirestoreImageState(reference, fallback, placeholder);
class FirestoreImageState extends State<FirestoreImage>
final Widget fallback;
final ImageProvider placeholder;
String _imageUrl;
bool _loaded = false;
_setImageData(dynamic url)
setState(()
_loaded = true;
_imageUrl = url;
);
_setError()
setState(()
_loaded = false;
);
FirestoreImageState(
StorageReference reference, this.fallback, this.placeholder)
reference.getDownloadURL().then(_setImageData).catchError((err)
_setError();
);
@override
Widget build(BuildContext context) => _loaded
? FadeInImage(
image: NetworkImage(_imageUrl),
placeholder: placeholder,
)
: fallback;
旧答案:
我刚刚开始使用 Flutter (Dart) 进行开发,所以我的答案肯定不会完美(甚至可能很糟糕),但我是这样做的:
import 'dart:typed_data';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
class FirestoreImage extends StatefulWidget
final StorageReference _reference;
FirestoreImage(this._reference);
@override
FirestoreImageState createState() => FirestoreImageState(_reference);
class FirestoreImageState extends State<FirestoreImage>
Uint8List _imageData;
_setImageData(Uint8List data)
setState(()
_imageData = data;
);
FirestoreImageState(StorageReference reference)
reference
.getData(0x3FFFFFFF)
.then(_setImageData)
.catchError((err) );
@override
Widget build(BuildContext context) =>
_imageData == null ? Container() : Image.memory(_imageData);
现在您可以通过调用new FirestoreImage(imageStorageReference)
来显示FirestoreImage
。也许通过扩展Image
有更好的方法
【讨论】:
【参考方案2】:VizGhar 提供了一个nice solution。 我已经清理了课程,添加了一些功能和文档。
this gist 上也有。
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
enum ImageDownloadState Idle, GettingURL, Downloading, Done, Error
class FirebaseStorageImage extends StatefulWidget
/// The reference of the image that has to be loaded.
final StorageReference reference;
/// The widget that will be displayed when loading if no [placeholderImage] is set.
final Widget fallbackWidget;
/// The widget that will be displayed if an error occurs.
final Widget errorWidget;
/// The image that will be displayed when loading if no [fallbackWidget] is set.
final ImageProvider placeholderImage;
FirebaseStorageImage(
Key key,
@required this.reference,
@required this.errorWidget,
this.fallbackWidget,
this.placeholderImage)
assert(
(this.fallbackWidget == null && this.placeholderImage != null) ||
(this.fallbackWidget != null && this.placeholderImage == null),
"Either [fallbackWidget] or [placeholderImage] must not be null.");
@override
_FirebaseStorageImageState createState() => _FirebaseStorageImageState(
reference, fallbackWidget, errorWidget, placeholderImage);
class _FirebaseStorageImageState extends State<FirebaseStorageImage>
with SingleTickerProviderStateMixin
_FirebaseStorageImageState(StorageReference reference, this.fallbackWidget,
this.errorWidget, this.placeholderImage)
var url = reference.getDownloadURL();
this._imageDownloadState = ImageDownloadState.GettingURL;
url.then(this._setImageData).catchError((err)
this._setError();
);
/// The widget that will be displayed when loading if no [placeholderImage] is set.
final Widget fallbackWidget;
/// The widget that will be displayed if an error occurs.
final Widget errorWidget;
/// The image that will be displayed when loading if no [fallbackWidget] is set.
final ImageProvider placeholderImage;
/// The image that will be/has been downloaded from the [reference].
Image _networkImage;
/// The state of the [_networkImage].
ImageDownloadState _imageDownloadState = ImageDownloadState.Idle;
/// Sets the [_networkImage] to the image downloaded from [url].
void _setImageData(dynamic url)
this._networkImage = Image.network(url);
this
._networkImage
.image
.resolve(ImageConfiguration())
.addListener((_, __)
if (mounted)
setState(() => this._imageDownloadState = ImageDownloadState.Done);
);
if (this._imageDownloadState != ImageDownloadState.Done)
this._imageDownloadState = ImageDownloadState.Downloading;
/// Sets the [_imageDownloadState] to [ImageDownloadState.Error] and redraws the UI.
void _setError()
if (mounted)
setState(() => this._imageDownloadState = ImageDownloadState.Error);
@override
Widget build(BuildContext context)
switch (this._imageDownloadState)
case ImageDownloadState.Idle:
case ImageDownloadState.GettingURL:
case ImageDownloadState.Downloading:
return Image(image: this.placeholderImage) ?? this.fallbackWidget;
case ImageDownloadState.Error:
return this.errorWidget;
case ImageDownloadState.Done:
return this._networkImage;
break;
default:
return this.errorWidget;
【讨论】:
很高兴有人完成了它:)【参考方案3】:不可能(还)。您需要自己将该 uri 存储在数据库中。
但您可以并且应该使用 getData
而不是在 Firebase 应用中使用下载网址。
【讨论】:
感谢您的澄清。getData()
在参数中要求 FuturegetDownloadURL
在回答时不存在以上是关于如何以单独的方法获取 Flutter Firebase 存储?的主要内容,如果未能解决你的问题,请参考以下文章
如何从我的简单.dart文件创建插件以在Flutter中使用?
如何在 Flutter 中从 Firebase Auth 获取用户 ID?