Download the next screen's image while the user is still on the list. Image.prefetch(url) fills the disk cache and resolves to true; queryCache(urls) reports 'memory', 'disk' or 'disk/memory' per cached URL; and getSize(url) resolves to the pixel size. The demos serve the covers with python3 -m http.server 8000 --directory assets/covers, and adb reverse tcp:8000 tcp:8000 makes that port localhost:8000 on the emulator.
const urls = books.map((b) => coverUrl(b.id));
export function usePrefetchedCovers() {
const [ready, setReady] = useState(false);
useEffect(() => {
(async () => {
console.log('before', await Image.queryCache?.(urls.slice(0, 2)));
const t0 = Date.now();
const ok = await Promise.all(urls.map((url) => Image.prefetch(url)));
console.log(`prefetched ${ok.filter(Boolean).length} in ${Date.now() - t0} ms`);
console.log('after', await Image.queryCache?.(urls.slice(0, 2)));
console.log('size', await Image.getSize(urls[0]));
setReady(true);
})().catch((e) => console.warn('prefetch failed', e));
}, []);
return ready;
} LOG before {}
LOG prefetched 6 in 2376 ms
LOG after {"http://localhost:8000/1.png": "disk", "http://localhost:8000/2.png": "disk"}
LOG size {"height": 600, "width": 400}queryCache is optional in the TypeScript types, hence the ?.. After a fresh install the cache was empty ({}); the prefetch put all six covers on disk in 2.4 seconds, and getSize read the 400 x 600 pixel size without drawing anything. Prefetch only what the user will probably open next: the core Image cannot evict anything.