Skip to main content

Global Cache

The instance of the query cache is available through a singleton CachedQuery.instance. It has a few useful utilities on it.

Where Query

Where query works much like where on an iterable. It returns a list of queries and infinite queries that satisfy the given test.

The example below returns all queries/infinite queries whose key contains the word "Post".

Note: The key on a query object will always be a string

final queries = CachedQuery.instance.whereQuery((query) => query.key.contains("post"));

Re-fetch, Invalidate and Delete

Use the Cached Query instance to easily invalidate or re-fetch the whole cache or a single key.

Refetch multiple queries at once by passing a list of keys.

CachedQuery.instance.refetchQueries(keys: ["posts"]);

Refetch multiple queries at once by passing a filter.

CachedQuery.instance.refetchQueries(
filterFn: (unencodedKey, key) => key.startsWith("todos/"),
);

Invalidating will mark the specified key as stale. To invalidate the whole cache don't pass a key.

CachedQuery.instance.invalidateCache(key: "posts");

// Invalidate the whole cache
CachedQuery.instance.invalidateCache();

Deleting will remove the specified key immediately. To delete the whole cache leave the key as null.

// Optionally delete the stored values as well.
CachedQuery.instance.deleteCache(key: "posts", deleteStorage: true);

// Delete the whole cache
CachedQuery.instance.deleteCache(deleteStorage: true);

Manually Adding and Removing Queries

You can manually add or get a query from the cache, although it is not normally necessary to add it as the query will call this for you.

To add a query or infinite query to cache:

CachedQuery.instance.addQuery(query);

To get a query or infinite query from cache:

CachedQuery.instance.getQuery(key);

Updating the Cache

It is often useful to be able to update the cache manually, for example, when performing optimistic updates

Use updateQuery to update a query or an infinite query. Any changes will be emitted down the query stream. The update function requires either a key or a filterFn to select the query to update. The updateFn is then called with the current data and should return the new data.

CachedQuery.instance.updateQuery(
key: "posts",
updateFn: (dynamic old) {
if (old is List<List<PostModel>>) {
return <List<PostModel>>[
[newPost, ...old[0]],
...old.sublist(1).toList()
];
}
},
);
info

As an alternative to using CachedQuery.instance.updateQuery you can also use the whereQuery method in tandem with the update method on the query object itself.

This would have better type safety but would result in more code. ``

Query Key Filter Function

Many of the functions on the CachedQuery instance take a key or a filterFn. A key is a direct reference to a cached query where as the filterFn allows for selecting multiple queries at once.

For example, say you have a list of todos, and each todo has been fetched with the key "todos/${id}", if a user selects a "complete all" button then we will want to find all the todos in the cache and update them, regardless of their id.

CachedQuery.instance.updateQuery(
updateFn: (dynamic oldData){
if(oldData is Todo){
return oldData?.copyWith(complete: true);
}
},
filterFn: (unencodedKey, key) => key.startsWith("todos/"),
);

Notice that the filterFn passes through two arguments; unencodedKey and key. The unencodedKey is the original key the you passed to the query. The key is the json-encoded string of the unencodedKey. Using the example above, if the todo keys were altered to be ["todo", id] then we could use the unencoded key to filter the queries.

CachedQuery.instance.updateQuery<Todo>(
updateFn: (dynamic oldData){
if(oldData is Todo){
return oldData?.copyWith(complete: true);
}
},
filterFn: (unencodedKey, key) => unencodedKey is List && unencodedKey.first == "todo",
);