So, my users might not have access to the internet but still request something. The BaseCacheManager will return the cached file (for which the validity has run out), and while trying to download the updated version it will throw a SocketException:
SocketException: Failed host lookup: 'url here' (OS Error: No address associated with hostname, errno = 7).
I tried to catch this error, but for some reason it didn't get caught. I thought it was because the getSingleFile function will execute the unawaited(downloadFile(url)) and return the (old) cached file. That way the old cached file will pass through the try/catch block no problem, but the unawaited function will give an exception. I tried changing this by making my getSingleFile like this:
@override
Future<File> getSingleFile(String url, {Map<String, String> headers}) async {
FileInfo cacheFile = await getFileFromCache(url);
if (cacheFile != null) {
if (cacheFile.validTill.isBefore(DateTime.now())) {
cacheFile = await downloadFile(url, authHeaders: headers);
}
return cacheFile.file;
}
return (await downloadFile(url, authHeaders: headers)).file;
}
This fixed it, but I'd like to have the functionality of still getting the outdated cached file even when downloading the new one failed, while letting the user know that they are looking at an outdated file, which is not possible doing it like this.
Does anyone have an idea how I can still catch the SocketException when using unawaited?
Thanks
The library just shows the cached image when you don't have an internet connection. The cached file could be outdated, but it can also be that it is still perfectly up to date. Why do you want to show the user the image might not be up to date?
You can also just show a general banner that the user has no connectivity
@renefloor So it isn't normal that it throws a socketException when there's not internet connection?
My application just gives some knowledge about certain things and I want people to know that the info they're looking at can be outdated.
Anyway, I'm starting to think that I don't really need a library like this one, still very much appreciated for the answer
@JasperSurmont how and where do you see the exception? You might see it in the logs, but it shouldn't crash
@renefloor So I tried to check when it throws this exception. When debugging I couldn't really follow. It seemed like everything went alright, and suddenly out of nowhere the exception is thrown and caught by one of my catches, but I had no idea where exactly it was caught.
I checked it by adding some prints:
I have my CustomCacheManager class, in which i defined my getSingleFile as follows:
@override
Future<File> getSingleFile(String url, {Map<String, String> headers}) async {
FileInfo cacheFile = await getFileFromCache(url);
if (cacheFile != null) {
if (cacheFile.validTill.isBefore(DateTime.now())) {
try {
cacheFile = await downloadFile(url, authHeaders: headers);
} on SocketException catch(e, stacktrace) {
print('in getSingleFile');
Crashlytics.instance.recordError(e, stacktrace);
}
}
return cacheFile.file;
}
return (await downloadFile(url, authHeaders: headers)).file;
The function that called my CustomCacheManager's getSingleFile looked as follows.
void searchStart(String url) async {
CustomCacheManager cacheMgr = CustomCacheManager();
FileInfo result;
try {
result = await cacheMgr.getSingleFile(url);
} on SocketException catch (e, stacktrace) {
Crashlytics.instance.recordError(e, stacktrace);
print('In searchStart');
}
}
For some reason, when I try to execute the searchStart method, I get the following logs:
_I/flutter (19687): Error caught by Crashlytics plugin
I/flutter (19687): SocketException: Failed host lookup: 'url here' (OS Error: No address associated with hostname, errno = 7)
I/flutter (19687): In searchStart_
This means that the error didn't get caught in the getSingleFile but it did higher up in the searchStart method? How is this possible?
Thanks for your patience if I'm being a dumbdumb
In this case it could be that the file wasn't in the cache at all and crashes because of return (await downloadFile(url, authHeaders: headers)).file; ?
Ah well that's the only explanation
@renefloor
Would you consider exporting classes CacheManager and DefaultCacheManager, so that developers can more easily extend them with custom functionality?
My use case here is similar to the one @JasperSurmont have.
I'm getting quite a lot of Crashlytics non-fatal errors with SocketException: Failed host lookup and I would love to do something about them.
Using yours CacheManager and just overriding downloadingFile would be ideal for me, because that would let me keep all the existing, stable logic and just slightly change error handling.
I also encountered this problem. I need a way to get SocketException so that I can do something in my global environment.
I have the same issue as @renefloor - errors related to cached_network_image when offline account for 60-70% of my Crashlytics logging. Our app is offline first, so this is logging we'd like to swallow.
Add an additional onError callback that defaults to FlutterError.reportError (ie, the default Flutter behaviour)
CachedNetworkImage(
imageUrl: ...,
errorHandler: FlutterError.reportError, // Default behaviour
),
This way we can swallow the error by passing a NOP function, ie:
CachedNetworkImage(
imageUrl: ...,
errorHandler: (){ }, // Swallow errors
),
Most helpful comment
@renefloor
Would you consider exporting classes
CacheManagerandDefaultCacheManager, so that developers can more easily extend them with custom functionality?My use case here is similar to the one @JasperSurmont have.
I'm getting quite a lot of Crashlytics non-fatal errors with
SocketException: Failed host lookupand I would love to do something about them.Using yours
CacheManagerand just overridingdownloadingFilewould be ideal for me, because that would let me keep all the existing, stable logic and just slightly change error handling.