Pixels is an offline-first photography and wallpaper explorer for Android. Powered by the Pexels REST API, Clean Architecture, and AndroidX Room, it features two-stage progressive image rendering, gesture pinch-to-zoom, Shimmer skeleton loaders, native background wallpaper downloading, and intelligent rate-limit-preserving cache management.
Pixels is engineered according to Clean Architecture principles, cleanly separating data sources, domain business use cases, and presentation layers:
- Curated & Real-Time Search: Explore trending curated photography collections or execute real-time searches across millions of high-resolution stock photos.
- Offline-First Persistence: Powered by AndroidX Room with automatic Time-To-Live (TTL) cache eviction, query-based invalidation, and rate-limit guard rails that serve cached assets when API quota runs low.
- Two-Stage Progressive Image Loading: Delivers instant visual response by rendering lightweight cached thumbnails through Coil 3, progressively swapping in ultra-high-resolution imagery in the background without UI stutter.
- Pinch-To-Zoom Detail Canvas: Immersive fullscreen viewer built with PhotoView, featuring gesture zoom, dominant-color background placeholders, creator attribution, and one-tap Android
DownloadManagerexport.
flowchart TD
subgraph Presentation ["Presentation Layer (MVVM)"]
MainActivity[MainActivity\nCurated Grid & Search Bar]
DetailActivity[DetailActivity\nPhotoView Pinch-Zoom & BottomSheet]
MainVM[MainViewModel\nStateFlow / UiState]
DetailVM[DetailViewModel]
end
subgraph Domain ["Domain Layer (Use Cases)"]
GetCuratedUC[GetCuratedPhotosUseCase]
SearchUC[SearchPhotosUseCase]
PhotoModel[Photo Domain Model]
end
subgraph Data ["Data Layer & Repository"]
Repo[PhotoRepositoryImpl]
RateLimitGuard{Rate Limit\nRemaining <= 5?}
CacheCheck{Page 1 &\nCache Valid < TTL?}
VolleyService[PexelsApiService\nVolley Request Queue]
PexelsAPI[(Pexels REST API)]
RoomDB[(PixelsDatabase / Room)]
PhotoDao[PhotoDao]
EntityMapper[PhotoEntityMapper]
end
MainActivity --> MainVM
DetailActivity --> DetailVM
MainVM --> GetCuratedUC
MainVM --> SearchUC
GetCuratedUC --> Repo
SearchUC --> Repo
Repo --> CacheCheck
CacheCheck -->|Valid Cache Hit| RoomDB
CacheCheck -->|Cache Miss / Stale| RateLimitGuard
RateLimitGuard -->|Credits Low| RoomDB
RateLimitGuard -->|Proceed| VolleyService
VolleyService --> PexelsAPI
PexelsAPI -->|JSON Response| EntityMapper
EntityMapper --> RoomDB
RoomDB --> PhotoDao
PhotoDao --> Repo
Repo --> MainVM
- 🌟 Curated & Dynamic Search: Infinite scrolling feed of curated photos and instant keyword-based query search.
- 💾 Intelligent Room Database Cache:
- Automatically caches photo metadata and image URLs locally in SQLite via Room.
- Rate-limit aware: protects against API 429 errors by serving cached responses when quota drops below threshold.
- Automated cache pruning: deletes records exceeding
CACHE_TTL_MSand caps maximum cached results.
- 🖼️ Two-Stage Progressive Image Loading:
- Instantly renders cached
mediumsize photos. - Asynchronously downloads and fades in
large2x/ original resolution assets.
- Instantly renders cached
- 🔍 Interactive PhotoView Viewer: Full pinch-to-zoom, pan, double-tap zoom, and immersive tap-to-hide metadata overlays.
- 🎨 Dynamic Color Placeholders: Extracts average hex colors from Pexels metadata to display smooth color placeholder backdrops before images finish loading.
- 📥 Native Wallpaper Downloader: Integrates Android
DownloadManagerwith notification progress bars to download full-resolution pictures to the publicPictures/Pixels/gallery directory. - ⚡ Shimmer Loading Skeletons: Integrated Facebook Shimmer effects providing sleek placeholder transitions during network fetches.
- 💉 Service Locator DI: Clean, decoupled dependency injection without reflection overhead or code generation bloat.
| Layer / Component | Class Path | Responsibility |
|---|---|---|
| Gallery Feed | com.webscare.pixels.presentation.main.MainActivity | Curated photo grid, search view, swipe-to-refresh, shimmer placeholder |
| Pinch-Zoom Detail | com.webscare.pixels.presentation.detail.DetailActivity | Full-screen PhotoView zoom canvas, download trigger, share intent |
| State Machine | com.webscare.pixels.presentation.state.UiState | Sealed class modeling Loading, Success, Error, and Empty UI states |
| Curated Use Case | com.webscare.pixels.domain.usecase.GetCuratedPhotosUseCase | Domain business logic orchestrating curated photo requests |
| Search Use Case | com.webscare.pixels.domain.usecase.SearchPhotosUseCase | Domain business logic executing query-based photo lookups |
| Repository | com.webscare.pixels.data.repository.PhotoRepositoryImpl | Single source of truth managing network fetches, rate limits, and Room cache |
| Local Database | com.webscare.pixels.data.local.db.PixelsDatabase | Room database schema and DAO provider |
| DAO Interface | com.webscare.pixels.data.local.db.PhotoDao | SQL queries for TTL pruning, query lookups, and batch insertions |
| REST Network Engine | com.webscare.pixels.data.remote.PexelsApiService | Volley HTTP request pipeline with authorization header injection |
| Dependency Locator | com.webscare.pixels.di.ServiceLocator | Central singleton provider for repositories, DAOs, and network clients |
| Layer | Technology / Library | Version | Purpose |
|---|---|---|---|
| OS / Platform | Android | SDK 26 – 36 (Java 11) | Core Android runtime |
| Language | Kotlin | 2.1.21 | Modern null-safe application logic |
| Architecture | Clean Architecture + MVVM | — | Separation of concerns (Presentation, Domain, Data) |
| Local Database | AndroidX Room (via KSP) | 2.7.1 | SQLite database caching and offline persistence |
| Image Loading | Coil 3 + OkHttp Network Artifact | 3.1.0 | High-performance asynchronous image rendering |
| Zoom Canvas | PhotoView (Chris Banes) | 2.3.0 | Multi-touch pinch-to-zoom and pan gesture engine |
| Networking | Android Volley | 1.2.1 | HTTP request queue & REST API client |
| Shimmer UI | Facebook Shimmer Android | 0.5.0 | Skeleton loading placeholder animations |
| Lifecycle | AndroidX Lifecycle & ViewModel KTX | 2.9.1 | Reactive lifecycle-aware state management |
| Concurrency | Kotlin Coroutines Android | 1.10.2 | Structured asynchronous concurrency |
- Android Studio Ladybug / Meerkat (AGP
9.2.0, Gradle8.11+) - JDK 17 / 21
- Android SDK 36 (minSdk 26 — Android 8.0 Oreo or higher)
- A free Pexels API Key
Clone the repository:
git clone https://github.com/shayann07/Pixels.git cd PixelsConfigure Pexels API Key: Create a
local.propertiesfile in the project root (if not already present) and add your API key:PEXELS_API_KEY=your_pexels_api_key_hereBuild & Run:
./gradlew assembleDebug
Launch the app on an Android device or emulator. Curated photos will populate instantly, and previously loaded photos will remain fully accessible offline!
This project is licensed under the MIT License — Copyright (c) 2026 shayann07.