I have the following code where I fetch an image from firebase storage as an Image. Now, I want to store this image in my CachedNetworkImage so that I don't have to fetch it every time from the DB. Since the cache.networkimage expects a URL and I am fetching an Image, how do I use the cache.networkimage?
Here's my code;
final FirebaseStorage storage = FirebaseStorage(
app: Firestore.instance.app,
storageBucket: 'gs://my-project.appspot.com');
Uint8List imageBytes;
String errorMsg;
_MyHomePageState() {
storage.ref().child('selfies/me2.jpg').getData(10000000).then((data) =>
setState(() {
imageBytes = data;
})
).catchError((e) =>
setState(() {
errorMsg = e.error;
})
);
}
@override
Widget build(BuildContext context) {
var img = imageBytes != null ? Image.memory(
imageBytes,
fit: BoxFit.cover,
) : Text(errorMsg != null ? errorMsg : "Loading...");
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new ListView(
children: <Widget>[
img,
],
));
}
}```
Try this way out using firebase_image package. From here . You need to sync with image url (selfies/me2.jpg) and bucket url (gs://my-project.appspot.com)
Image(
image: FirebaseImage('gs://bucket123/userIcon123.jpg'),
// Works with standard parameters, e.g.
fit: BoxFit.fitWidth,
width: 100,
// ... etc.
)
Check out cached_network_image: ^2.5.0 package.
How to use it?
CachedNetworkImage(
imageUrl: "http://via.placeholder.com/350x150",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
I'm not Fire-store user, but this should work.
It might needs a little modification or something, please share in a comment to update my answer according to that
You can get file object as follow..
import 'dart:io';
import 'dart:typed_data';
Uint8List readyData = imageBytes;
File('my_image.jpg').writeAsBytes(bodyBytes);
and save it using image_gallery_saver , so the code should look like
Future<String> _createFileFromString() async {
final encodedStr = "...";
Uint8List bytes = base64.decode(imageBytes);
String dir = (await getApplicationDocumentsDirectory()).path;
String fullPath = '$dir/abc.png';
print("local file full path ${fullPath}");
File file = File(fullPath);
await file.writeAsBytes(bytes);
print(file.path);
final result = await ImageGallerySaver.saveImage(bytes);
print(result);
return file.path;
}
The package Cached network image depends on another package called Flutter cache manager in order to store and retrieve image files.
You need to download your image files and put them in the cache using the package. Here is an example code that gets files and their download urls from Firebase Storage and put them in the cache:
// import the flutter_cache_manager package
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
// ... other imports
class MyCacheManager {
Future<void> cacheImage() async {
final FirebaseStorage storage = FirebaseStorage(
app: Firestore.instance.app,
storageBucket: 'gs://my-project.appspot.com',
);
final Reference ref = storage.ref().child('selfies/me2.jpg');
// Get your image url
final imageUrl = await ref.getDownloadURL();
// Download your image data
final imageBytes = await ref.getData(10000000);
// Put the image file in the cache
await DefaultCacheManager().putFile(
imageUrl,
imageBytes,
fileExtension: "jpg",
);
}
}
Next, you will use CacheNetworkImage
widget as it shown in the documentation .
// ... some code
@override
Widget build(BuildContext context) {
return Scaffold(
body: CachedNetworkImage(
imageUrl: "your_image_link_here",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
);
}
If you put your image files in the cache by using Flutter cache manager, Cached network image should retrieve them from the cache directly. If your image files expire or the cache is cleared somehow, it will download and put them in the cache for you.
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
class MyCacheManager {
final _storage = FirebaseStorage(
app: FirebaseFirestore.instance.app,
storageBucket: 'gs://my-project.appspot.com',
);
final defaultCacheManager = DefaultCacheManager();
Future<String> cacheImage(String imagePath) async {
final Reference ref = _storage.ref().child(imagePath);
// Get your image url
final imageUrl = await ref.getDownloadURL();
// Check if the image file is not in the cache
if ((await defaultCacheManager.getFileFromCache(imageUrl))?.file == null) {
// Download your image data
final imageBytes = await ref.getData(10000000);
// Put the image file in the cache
await defaultCacheManager.putFile(
imageUrl,
imageBytes,
fileExtension: "jpg",
);
}
// Return image download url
return imageUrl;
}
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _imageUrl;
@override
void initState() {
final myCacheManager = MyCacheManager();
// Image path from Firebase Storage
var imagePath = 'selfies/me2.jpg';
// This will try to find image in the cache first
// If it can't find anything, it will download it from Firabase storage
myCacheManager.cacheImage(imagePath).then((String imageUrl) {
setState(() {
// Get image url
_imageUrl = imageUrl;
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: _imageUrl != null
? CachedNetworkImage(
imageUrl: _imageUrl,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
: CircularProgressIndicator(),
),
);
}
}
For your storage instance use some method like so
Future<void> downloadURLExample() async {
String downloadURL = await storage.ref('selfies/me2.jpg')
.getDownloadURL();
// Within your widgets:
// CachedNetworkImage(imageUrl: downloadURL);
}
to get it working with Firebase Storage with included offline functionality I changed it that way
Future<String> cacheImage(String imagePath) async {
var fileinfo = await defaultCacheManager.getFileFromCache(imagePath);
if(fileinfo != null)
{
return fileinfo.file.path;
} else{
final Reference ref = _storage.child(imagePath);
// Get your image url
final imageUrl = await ref.getDownloadURL();
// Check if the image file is not in the cache
// Download your image data
final imageBytes = await ref.getData(10000000);
// Put the image file in the cache
var file = await defaultCacheManager.putFile(
imageUrl,
imageBytes!,
key: imagePath,);
return file.path;
}
}
for anyone still stuck with this.. try this required no hacks and uses CachedNetworkImageProvider built-in retrieval methods.
first screen:
CachedNetworkImage(
imageUrl: "https://whereismyimage.com",
progressIndicatorBuilder:
(context, url, progress) {
return CircularProgressIndicator(
value: progress.progress,
);
},
errorWidget: (context, url, error) => const Icon(Icons.error),
),
then second screen
Image(image: CachedNetworkImageProvider("https://whereismyimage.com)"),
The CachedNetworkImageProvider knows how to retrieve the cached image using the url.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.