i dont want to store image in cache.. iam using CachedNetworkImage for image loading..
I want know is there any option to remove or do not store image in cache like picasso..
my code:
var annotatedImg = CachedNetworkImage(
fit: BoxFit.fill,
imageUrl: Constants.IMAGE_BASE_URL + widget._fileId + Constants.CONTOUR_IMG_SUFFIX,
placeholder: (context, url) => progressBar,
errorWidget: (context, url, error) => new Icon(Icons.error),
);
i have tried
annotatedImg.cacheManager.emptyCache();
but its shows cant call emptyCache is null..
Since CachedNetworkImage version 2.3, all these solutions won't work because it cached images in 2 different places (DefaultCacheManager & NetworkImageProvider)
So the only solution is using the evictFromCache built-in method from CachedNetworkImage
like this:
Future _deleteImageFromCache() async {
String url = "your url";
await CachedNetworkImage.evictFromCache(url);
}
evictFromCache is a Static method so it doesn't require to have the CachedNetworkImage in your Widget tree, you can use it directly from any place.
I agree with MichaelM, Don't use CachedNetworkImage.If you show image like this :
Image.network(
_headImageUrl,
fit: BoxFit.fitHeight,
)
you can use those code to clean image cache:
PaintingBinding.instance.imageCache.clear();
Firstly add the package (flutter_cache_manager) to pubspec.yaml file as following:
dependencies:
flutter:
sdk: flutter
flutter_cache_manager: ^1.1.3
After a day, I found the solution. Use the DefaultCacheManager object by calling emptyCache() method, this clears the cache data.
DefaultCacheManager manager = new DefaultCacheManager();
manager.emptyCache(); //clears all data in cache.
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
await DefaultCacheManager().removeFile('YOUR_URL');
DONT USE emptyCache() from the first answer, it clear ALL your Cache
CachedNetworkImage stores the images in temporary(cache) folder, you can get access to it with path_provider's getTemporaryDirectory() method. There you will find libCachedImageData (You might need to check the name). There you can delete the folder.
To do it in your app you should use Directory class like:
final Directory tempDir = await getTemporaryDirectory();
final Directory libCacheDir = new Directory("${tempDir.path}/libCachedImageData");
await libCacheDir.delete(recursive: true);
If you do not want to store the downloaded image in a cache, then don't use CachedNetworkImage. Instead, use a FadeInImage widget with a NetworkImage:
FadeInImage(
// here `bytes` is a Uint8List containing the bytes for the in-memory image
placeholder: // This should be an image, so you can't use progressbar,
image: NetworkImage('https://backend.example.com/image.png'),
)
In your CachedNetworkImage, add CacheManager Config:
CachedNetworkImage(CacheManager(Config(
featureStoreKey,
stalePeriod: const Duration(seconds: 15),
maxNrOfCacheObjects: 1,
repo: JsonCacheInfoRepository(databaseName: featureStoreKey),
fileService: HttpFileService(),
),
),
fit: BoxFit.fill,
imageUrl: Constants.IMAGE_BASE_URL + widget._fileId + Constants.CONTOUR_IMG_SUFFIX,
placeholder: (context, url) => progressBar,
errorWidget: (context, url, error) => new Icon(Icons.error),
);
Then to clear it, add this void statement:
void _clearCache() {
try {
JsonCacheInfoRepository(databaseName: featureMain1Store).deleteDataFile();
} catch (e, s) {
print(s);
}
imageCache!.clear();
imageCache!.clearLiveImages();
setState(() {});
}
Related
i have been trying to get the download URL for my images in firebase storage so I can add it to my listview builders "NetworkCatched Images" for each of my items in the list, as you can see from my code below, I first declared a variable at the beginning of my stateful class called "URL" so I could change the value by making it equal to the download URL i get from firebase storage, but it seems like the async function I'm using doesn't even run because i made sure it prints out the value of the downloaded URL after it is done, but i see nothing in my debug console, where am going wrong here?
i keep getting this error No object exists at the desired reference.
by the way, the "thesnapshot.data()['image']" in my code is equal to the name of the image file e.g books.jpg which is the exact name of the file and it is in a folder called category as you can see below, would really appreciate some enlightenment on this, thanks
class Home extends State<HomeScreen> {
var url;
ListView.builder(shrinkWrap: true, padding: EdgeInsets.all(0), physics: NeverScrollableScrollPhysics(), itemCount: snapshot.data.documents.length, itemBuilder: (BuildContext context, int index)
{
DocumentSnapshot thesnapshot = snapshot.data.docs[index];
current_category = thesnapshot.data()['category'];
printUrl() async {
Reference ref = FirebaseStorage.instance.ref().child("category/" + thesnapshot.data()['image'].toString());
var togo = (await ref.getDownloadURL()).toString();
setState(() {
url = togo;
print(url);
});
}
printUrl();
I think that the .ref() included in your reference doesn't go thereas well as the thesnapshot.data()['image'].toString().
Try something like this
Future<void> downloadURLExample() async {
String downloadURL = await firebase_storage.FirebaseStorage.instance
.ref('users/123/avatar.jpg')
.getDownloadURL();
Extracted from the documentation
I am trying to get image from video url when my list scroll but when I use of video thumbnail library and call it in my app list freezes and my app crashed this is my code
Future _loadMore(context) async {
final directory=Provider.of<DirectoryPath>(context,listen: false);
Provider.of<LoadState>(context).setLoadState(true);
final index= Provider.of<IndexLazyloading>(context);
if(moves.length!=index.oldmove){
resetlist(context);
}
// Add in an artificial delay
for (var i = index.currentindex; i <= index.currentindex + increment && i<moves.length; i++) {
File f=new File( "${directory.directory}/${moves[i].videourl.split("/").last.replaceAll("mp4", "png")}");
if(!f.existsSync())
await getimage("${strings.baseurl}/videos/${moves[i].videourl}",context);
index.setdata(i);
}
await new Future.delayed(const Duration(seconds: 2));
Provider.of<LoadState>(context).setLoadState(false);
index.setcurrentIndex(index.data.length) ;
index.setoldMove(moves.length);
}
and this is my plugin that used
Future<Null> getimage(videourl,context)async{
final uint8list = await VideoThumbnail.thumbnailFile(
video: videourl,
thumbnailPath: Provider.of<DirectoryPath>(context).directory,
imageFormat: ImageFormat.WEBP,
maxHeightOrWidth: 0, // the original resolution of the video
quality: 75,
);
}
i try with png but dont work
this is my list that call this function what is problem in this code please help me
LazyLoadScrollView(
isLoading: loadstate.isload,
onEndOfPage: () => _loadMore(context),
child: ListView.builder(
itemCount: indexlayze.data.length,
itemBuilder: (context, position) {
return _buildProductItem(context,position);
},
));
my list get 10 image thumbnail when reach to end of list but is very slow how to handle it
How about dedicate this job to a NGINX/NodeJS service running on the cloud? Let the App just downloads the thumbnails from it. This is what I did before.
If you really need to generate the thumbnails by App, try couple things:
Use JPG/PNG instead of WebP because it costs a lot CPU on iOS
Create a list or stream to queue the requests, display a placeholder thumbnail before it done.
Priority the queue once ListView stops scrolling.
Signal the image component once the thumbnail finished, also take next item to call thumbnail
My goal is to open a CSV file from phone local storage ~/Downloads and import it into the DB.
I'm using Flutter and to this day I have looked over a dozen examples without a success.
However I was able to get contents of the file printed in the console, but for that I had to have a file in assets/res folder in the app project.
If I use getExternalStorageDirectory, I get emulated/storage/0/ as a result. How to get to device's internal storage (not external storage as phone used will not have an option for a SD card or if they will, it will not be used)?
For the DB, I was able to get a working example using sqflite, but I as I'm total noob, I can't get it to work within my already designed app.
Open the file as a text document using open_file from package:open_file/open_file.dart and parse the contents yourself.
See https://pub.dartlang.org/documentation/open_file/latest/
Back to beginning and yet a little bit closer to the solution I need. I have file_picker (https://pub.dartlang.org/packages/file_picker), which helps to pick file using file explorer:
String _filePath;
void getFilePath() async {
try {
String filePath = await FilePicker.getFilePath(
type: FileType.CUSTOM, fileExtension: 'csv');
if (filePath == '') {
return;
}
print("Path: " + filePath);
setState(() {
this._filePath = filePath;
});
} on PlatformException catch (e) {
print("Error picking file: " + e.toString());
}
}
Using above code returns the path of the file e.g. "/storage/emulated/0/Download/1.csv".
Now I use this path to read the contents of the file:
...
RaisedButton(
child: const Text('Import data - dummy'),
color: Theme.of(context).accentColor,
elevation: 4.0,
splashColor: Colors.blueGrey,
onPressed: () {
print('Verifying click done');
// Show contents of the file
readContents();
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: getFilePath,
tooltip: 'Choose file to import',
child: new Icon(Icons.sd_storage),
)
...
Future<File> get _localFile async {
final path = await _filePath;
return File('$path');
}
Future<int> readContents() async {
try {
final file = await _localFile;
// Read the file
String contents = await file.readAsString();
return int.parse(contents);
} catch (e) {
// If we encounter an error, return 0
return 0;
}
}
Now as the above code should return contents of a CSV file, it does nothing. CSV file contains a list of items.
Can somebody let me know why and be so kind to show me how I can save parsed content of a file to a string or even better strings which represent each column from the file?
THANKS!
Maybe my question will sound foolish, but here it is...
How can we get the path to a cached image (in both iOS and Android)?
Here is my use case: I present a view on my App that lists images from the web --> I get an array of urls from Google Customer Search API based on the user's provided keywords...
<FlatList
style={{ width: '100%' }}
data={this.state.suggestions}
numColumns={2}
renderItem={(img) => {
return (
<TouchableOpacity onPress={() => this.selectImageHandler(img.item)} >
<Image source={{ uri: img.item.link }} />
</TouchableOpacity>
)
}}
keyExtractor={(item, index) => index.toString()}
/>
The result looks like this:
Then the user presses on an image to select it, which then needs to store this image in the app's folder (PictureDir/myappfolder/ in Android, DocumentDir/myappfolder/ in iOS) ...
What I am doing right now is when the image is selected, I download it again:
selectImageHandler = (img) => {
// (... pre code ...)
RNFS.downloadFile({
fromUrl: img.link, // e.g. "http://www.url.to/the/picture.png
toFile: uri, // e.g. "file://"+PictureDir+ "/myAppFolder/picturename.jpg"
}).promise.then( res => {
// (... post code ...)
}
It works fine! But it takes a bit of time, as it downloads again the image,
but I feel this is doing it twice, as it was downloaded already a stored in the cache to be displayed.
So here comes my question again, is there a way to know where the image was stored in the cache, so that when the user pressed the image to save it, it will not download it again, but will rather move it from the cache folder to the app's folder?
Am I making any sense? Or is redownloading the right approach?
Thanks for your help!
One way to avoid re-downloading images a few times might be to take over the control of downloading from a remote url from the <Image> component. Basically, you can download the remote image using the RNFS.downloadFile method and then supply the local URI (toFile value) as the image source. This requires a bit more work, of course, as we need to create a wrapper component, but this approach also provides options to control the display of an image while it's loading.
For example:
import React, { useState, useLayoutEffect } from 'react';
import RNFS from 'react-native-fs';
import { URL } from 'react-native-url-polyfill';
const CACHE_DIR = RNFS.DocumentDirectoryPath; // Cross-platform directory
function ImageCard ({ imgUrl }) {
const [cachedImgUrl, setCachedImgUrl] = useState(null);
const [isImageLoading, setIsImageLoading] = useState(true);
useLayoutEffect(() => {
const getCachedImageUrl = async () => {
try {
const basename = new URL(imgUrl).pathname.split('/').pop();
const localImgUrl = `file://${CACHE_DIR}/${basename}`;
if (await RNFS.exists(localCacheUrl)) {
setCachedImgUrl(localImgUrl);
} else {
const download = RNFS.downloadFile({
fromUrl: imgUrl,
toFile: localImgUrl,
});
const downloadResult = await download.promise;
if (downloadResult.status === 200) {
setCachedImgUrl(localImgUrl);
}
}
} catch (err) {
// handle error
} finally {
setIsImageLoading(false);
}
};
getCachedImageUrl();
}, [imgUrl]);
if (isImageLoading || !cachedImgUrl) {
// A better idea would be to return some `<Loader />` component, or some placeholder, like skeleton animation, etc. This is just an example.
return null;
}
return (
<Image source={{ uri: localImgUrl }} />;
);
}
The <ImageCard /> component replaces the plain <Image /> component in the <FlatList /> and downloads from the remote image URL only once.
The code above is simplified and it assumes that you have unique image names that you can use as the identifiers on the file system, and that the image urls don't include any search parameters, etc. Please be cautious and adapt the code for your needs before using it directly.
I'm modifying Pesto example https://github.com/flutter/flutter/blob/76844e25da8806a3ece803f0e59420425e28a405/examples/flutter_gallery/lib/demo/pesto_demo.dart to receive new recipes from the net, by adding the following function:
void loadMore(BuildContext context, query) {
HttpClient client = new HttpClient();
client.getUrl(Uri.parse("http://10.0.2.2:5000/search/" + query ))
.then((HttpClientRequest request) {
return request.close();
})
.then((HttpClientResponse response) {
// Process the response.
response.transform(UTF8.decoder).listen((contents) {
// handle data
var decoded = JSON.decode(contents);
var rec = new Recipe(
name: decoded['title'],
author: decoded['author'],
professionIconPath: 'images/1.png',
description: decoded['description'],
imageUrl: 'http://example.jpg',
);
kPestoRecipes.add(job);
//Navigator.push(context, new MaterialPageRoute<Null>(
// settings: const RouteSettings(name: "/"),
// builder: (BuildContext context) => new PestoHome(),
//));
});
});
}
and I binded loading additional recipe to clicking interface button:
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.edit),
onPressed: () {
scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text('Adding new recipe')
));
loadMore(context, "test");
},
),
But how do I redraw home page when new recipe received? I've tried to
the part with Navigator you've seen commented out, but it didn't work. I also tried
new PestoDemo();
but it showed new recipe only for a moment and didn't feel like a proper way to do re-drawing.
You should call setState whenever you change data that affects what the build() function for a given State object returns:
https://docs.flutter.io/flutter/widgets/State/setState.html
For example:
setState(() {
_recipes.add(job);
});
If you do this, I'd recommend changing kPestoRecipes from being a global constant to being a private member variable of a State subclass. That will probably involve passing the list around from one widget to another rather than having all the widget refer to the global constant.
One other tip: when you get the HttpClientResponse, you should check the mounted property of the State object. If mounted is false, that means the widget has been removed from the tree and you might want to ignore the network response.