Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion flutter_cache_manager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ you call this method with other height/width parameters.
When your files are stored on Firebase Storage you can use [flutter_cache_manager_firebase](https://pub.dev/packages/flutter_cache_manager_firebase).

## Customize
The cache manager is customizable by creating a new CacheManager. It is very important to not create more than 1
The cache manager is customizable by creating a new CacheManager. It is very important to not create more than one
CacheManager instance with the same key as these bite each other. In the example down here the manager is created as a
Singleton, but you could also use for example Provider to Provide a CacheManager on the top level of your app.
Below is an example with other settings for the maximum age of files, maximum number of objects
Expand All @@ -85,6 +85,7 @@ class CustomCacheManager {
- [How are the cache files stored?](#how-are-the-cache-files-stored)
- [When are the cached files updated?](#when-are-the-cached-files-updated)
- [When are cached files removed?](#when-are-cached-files-removed)
- [Why are cached files kept even though the server sends max-age=0?](#why-are-cached-files-kept-even-though-the-server-sends-max-age0)


### How are the cache files stored?
Expand Down Expand Up @@ -113,6 +114,20 @@ The cache knows when files have been used latest. When cleaning the cache (which
deletes files when there are too many, ordered by last use, and when files just haven't been used for longer than
the stale period.

### Why are cached files kept even though the server sends max-age=0?

The case when a web server responds with `Cache-Control: max-age=0` is kind of an edge case.
It could either mean, that the content expires really fast (then `Cache-Control: no-cache` might
be a better response) or it could be that the server has some misconfiguration in place.

There where some confusions among users of this library because of the second case (see also
[this issue](https://github.com/Baseflow/flutter_cache_manager/issues/283) so as a default
behaviour this library ignores `max-age=0` and instead sets the validity of the downloaded file
to `Duration(days: 7)`.

If you want to treat `max-age=0` the same as `no-cache` (or something less rigid like 30 seconds), then
set the `Config` parameter `durationOnMaxAgeZero` to `Duration(seconds: 0)` or `30` or whatever you
think is appropriate.

## Breaking changes in v2
- There is no longer a need to extend on BaseCacheManager, you can directly call the constructor. The BaseCacheManager
Expand Down
11 changes: 10 additions & 1 deletion flutter_cache_manager/lib/src/config/_config_io.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ class Config implements def.Config {
Config(
this.cacheKey, {
Duration? stalePeriod,
Duration? durationOnMaxAgeZero,
int? maxNrOfCacheObjects,
CacheInfoRepository? repo,
FileSystem? fileSystem,
FileService? fileService,
}) : stalePeriod = stalePeriod ?? const Duration(days: 30),
durationOnMaxAgeZero = durationOnMaxAgeZero ?? const Duration(days: 7),
maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200,
repo = repo ?? _createRepo(cacheKey),
fileSystem = fileSystem ?? IOFileSystem(cacheKey),
fileService = fileService ?? HttpFileService();
fileService = fileService ??
HttpFileService(
durationOnMaxAgeZero: durationOnMaxAgeZero ??
Duration(days: 7),
);

@override
final CacheInfoRepository repo;
Expand All @@ -29,6 +35,9 @@ class Config implements def.Config {
@override
final Duration stalePeriod;

@override
final Duration durationOnMaxAgeZero;

@override
final int maxNrOfCacheObjects;

Expand Down
5 changes: 5 additions & 0 deletions flutter_cache_manager/lib/src/config/_config_unsupported.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class Config implements def.Config {
//ignore: avoid_unused_constructor_parameters
Duration? stalePeriod,
//ignore: avoid_unused_constructor_parameters
Duration? durationOnMaxAgeZero,
//ignore: avoid_unused_constructor_parameters
int? maxNrOfCacheObjects,
//ignore: avoid_unused_constructor_parameters
CacheInfoRepository? repo,
Expand All @@ -34,6 +36,9 @@ class Config implements def.Config {
@override
Duration get stalePeriod => throw UnimplementedError();

@override
Duration get durationOnMaxAgeZero => throw UnimplementedError();

@override
int get maxNrOfCacheObjects => throw UnimplementedError();

Expand Down
11 changes: 10 additions & 1 deletion flutter_cache_manager/lib/src/config/_config_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ class Config implements def.Config {
Config(
this.cacheKey, {
Duration? stalePeriod,
Duration? durationOnMaxAgeZero,
int? maxNrOfCacheObjects,
CacheInfoRepository? repo,
FileSystem? fileSystem,
FileService? fileService,
}) : stalePeriod = stalePeriod ?? const Duration(days: 30),
durationOnMaxAgeZero = durationOnMaxAgeZero ?? const Duration(days: 7),
maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200,
repo = repo ?? NonStoringObjectProvider(),
fileSystem = fileSystem ?? MemoryCacheSystem(),
fileService = fileService ?? HttpFileService();
fileService = fileService ??
HttpFileService(
durationOnMaxAgeZero: durationOnMaxAgeZero ??
Duration(days: 7),
);

@override
final CacheInfoRepository repo;
Expand All @@ -30,6 +36,9 @@ class Config implements def.Config {
@override
final Duration stalePeriod;

@override
final Duration durationOnMaxAgeZero;

@override
final int maxNrOfCacheObjects;

Expand Down
5 changes: 5 additions & 0 deletions flutter_cache_manager/lib/src/config/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ abstract class Config {
/// [stalePeriod] is the time duration in which a cache object is
/// considered 'stale'. When a file is cached but not being used for a
/// certain time the file will be deleted.
/// [durationOnMaxAgeZero] is the time duration a fetched API response is
/// considered up-to-date if the server responds with "max-age=0"
/// [maxNrOfCacheObjects] defines how large the cache is allowed to be. If
/// there are more files the files that haven't been used for the longest
/// time will be removed.
Expand All @@ -23,6 +25,7 @@ abstract class Config {
factory Config(
String cacheKey, {
Duration stalePeriod,
Duration durationOnMaxAgeZero,
int maxNrOfCacheObjects,
CacheInfoRepository repo,
FileSystem fileSystem,
Expand All @@ -33,6 +36,8 @@ abstract class Config {

Duration get stalePeriod;

Duration get durationOnMaxAgeZero;

int get maxNrOfCacheObjects;

CacheInfoRepository get repo;
Expand Down
14 changes: 9 additions & 5 deletions flutter_cache_manager/lib/src/web/file_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ abstract class FileService {
/// [WebHelper]. One can easily adapt it to use dio or any other http client.
class HttpFileService extends FileService {
final http.Client _httpClient;
final Duration _durationOnMaxAgeZero;

HttpFileService({http.Client? httpClient})
: _httpClient = httpClient ?? http.Client();
HttpFileService({http.Client? httpClient, Duration? durationOnMaxAgeZero})
: _httpClient = httpClient ?? http.Client(),
_durationOnMaxAgeZero = durationOnMaxAgeZero ?? Duration(days: 7);

@override
Future<FileServiceResponse> get(String url,
Expand All @@ -36,7 +38,7 @@ class HttpFileService extends FileService {
}
final httpResponse = await _httpClient.send(req);

return HttpGetResponse(httpResponse);
return HttpGetResponse(httpResponse, _durationOnMaxAgeZero);
}
}

Expand Down Expand Up @@ -64,12 +66,14 @@ abstract class FileServiceResponse {

/// Basic implementation of a [FileServiceResponse] for http requests.
class HttpGetResponse implements FileServiceResponse {
HttpGetResponse(this._response);
HttpGetResponse(this._response, this._durationOnMaxAgeZero);

final DateTime _receivedTime = clock.now();

final http.StreamedResponse _response;

final Duration _durationOnMaxAgeZero;

@override
int get statusCode => _response.statusCode;

Expand All @@ -86,7 +90,7 @@ class HttpGetResponse implements FileServiceResponse {
@override
DateTime get validTill {
// Without a cache-control header we keep the file for a week
var ageDuration = const Duration(days: 7);
var ageDuration = _durationOnMaxAgeZero;
final controlHeader = _header(HttpHeaders.cacheControlHeader);
if (controlHeader != null) {
final controlSettings = controlHeader.split(',');
Expand Down
5 changes: 2 additions & 3 deletions flutter_cache_manager/lib/src/web/web_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ const statusCodesNewFile = [HttpStatus.ok, HttpStatus.accepted];
const statusCodesFileNotChanged = [HttpStatus.notModified];

class WebHelper {
WebHelper(this._store, FileService? fileFetcher)
: _memCache = {},
fileFetcher = fileFetcher ?? HttpFileService();
WebHelper(this._store, this.fileFetcher)
: _memCache = {};

final CacheStore _store;
@visibleForTesting
Expand Down