Aug 2026 · 2 min read
Building Pixedge: A Wallpaper Feed That Stays Smooth With a Smart Image Pipeline
Wallpaper apps look simple. Pixedge’s real work is an image pipeline that prioritizes what you see and never double-fetches the same URL.
- flutter
- wallpaper
- performance
- caching
- image-pipeline
- mobile

I shipped Pixedge — a wallpaper app with the usual product shell: browse, like, download, set home/lock screen, premium limits, ads, remote config.
Users don’t judge wallpaper apps by architecture diagrams. They judge them by whether scrolling a dense grid stutters, and whether opening a detail view waits on a redundant re-download.
So the interesting work is SmartImageService.
The failure mode of naive image grids
Every tile wants a thumb. Every detail wants a full image. Without discipline you get:
- duplicate downloads for the same URL
- disk keys that collide or change across process restarts (
hashCodeis not a content key) - thumb re-encodes that burn CPU while the user is mid-scroll
- full-image requests stuck behind a backlog of off-screen thumbnails
What the pipeline actually does
- Memory maps for thumb vs full paths, checked before any work.
- Stable disk keys — FNV-style hash of the URL plus length, so paths survive restarts and avoid Dart
hashCodecollisions. - In-flight Future map — parallel tiles requesting the same URL share one Future.
- Priority queue — full images enqueue at the front; thumbs at the back. Max 4 concurrent processors.
- Thumb shortcut — if the cache-manager file is already under ~350KB, reuse it and skip a costly re-encode.
- Otherwise download via cache manager, compress with
flutter_image_compress, write the stable path, complete waiters.
That is not glamorous. It is why the grid feels intentional on a mid-range Android device.
Setting a wallpaper is a system fight
WallpaperService serializes operations (_isOperationInProgress), validates the file, maps location to home/lock/both, and retries with backoff when the OEM wallpaper API flakes. Double-tap while a set is in flight gets a toast, not a race.
Local state for downloads/likes uses Isar. The backend companion (pixedge_backend) is a separate Laravel content plane — the mobile post should stay about the client pipeline unless you’re writing a CMS piece.
What I’d still harden
Eviction policy for the temp disk cache under storage pressure. Metrics on queue wait time vs decode time. And OEM wallpaper APIs will keep inventing new ways to fail — keep the retry budget explicit.
Bet: media apps are judged by cache discipline, not by the tile radius.
If you’re shipping image-heavy Flutter apps: prioritize the visible request, dedupe the invisible ones, and never use hashCode as a file name.
Tagged
- flutter
- wallpaper
- performance
- caching
- image-pipeline
- mobile
Related work
Apps, packages, and projects this piece connects to.
More writing
Other notes from the archive.

Building Lexora: A Privacy-First Writing Keyboard That Works Offline
Lexora is an Android keyboard that helps people improve spelling, grammar, clarity, and tone wherever they write. Here is how I built its on-device writing engine, custom keyboard, and fast Android integration without sending text to a server.
Oct 2026 · 7 min read

Building iDraw: A Flutter Drawing App With Lessons, a Studio, and an AI Coach
iDraw is a Flutter app I’m building to help people learn to draw — guided lessons, a freehand studio, progress tracking, and an AI coach powered by Google Gemini. Here’s the product brief and the tech behind the strokes.
Sep 2026 · 5 min read

Building a scripting language for hardware panels
Rushabh's lab instruments speak in fixed-width serial strings, and every new panel meant another hardcoded Android screen. So I built a language instead: a lexer, a typed statement tree, an expression evaluator, and buttons you place on a photograph of the machine.
Aug 2026 · 7 min read
Discussion
Questions or notes. Comments live on GitHub Discussions.