signalapp / signalapp/Signal-Android
Media picker extremely slow to open on devices with large photo libraries (50k+ items)
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 29.4k
- Forks
- 6.9k
- PR merge metrics
- No merged PRs in 30d
Description
Guidelines
- I have searched searched open and closed issues for duplicates
- I am submitting a bug report for existing functionality that does not work as intended
- This isn't a feature request or a discussion topic
Bug description
Summary
The media picker takes several minutes to open on devices with large photo libraries (10,000-50,000+ photos/videos). The app appears frozen while the gallery loads.
Steps to Reproduce
- Use a device with a large media library (50,000+ photos/videos)
- Open any conversation in Signal
- Tap the attachment button and select the gallery
- Observe load time
Expected Behavior
Gallery opens within 1–2 seconds, showing the most recent items first, with more loading as you scroll.
Actual Behavior
Gallery takes minutes to open. The UI is unresponsive until all media has loaded.
Root Cause
The media picker loads the entire library into memory before displaying anything.
What happens internally
MediaStore queries do not read actual files—they query Android's internal SQLite database for metadata. However, the current implementation still causes major delays because:
-
No pagination: MediaRepository.getMediaInBucket() filters by folder ("bucket") but loads all items within that folder without a
LIMITclause. When "All Media" is selected, the folder filter is removed and it returns every photo/video on the device. -
Massive object allocations: Each of 100k rows creates
Media,Uri, andStringobjects—hundreds of thousands of allocations causing GC pressure. -
Two queries + in-memory merge + sort: Images and videos are fetched separately, merged, then sorted in memory with
Collections.sort(). -
UI blocked: The ViewModel waits for the complete list before submitting anything to the RecyclerView, so users see nothing until the entire process finishes.
Key insight
The bottleneck is not file I/O. It's cursor iteration over 100k rows, object allocations, and blocking the UI while waiting for the full dataset.
Affected Code
- MediaRepository.getMediaInBucket() — unbounded queries, full cursor iteration
- MediaGalleryViewModel.loadItemsForBucket() — maps entire list before UI update
Suggested Fix
- Implement pagination (Paging3 or
LIMIT/OFFSETqueries) - Load only the first 200–500 items for fast initial render
- Load more items on scroll
- Consider
MediaStore.Fileswith media type filter to avoid two queries
Impact
Severe UX degradation for users with large photo libraries. The app appears frozen when trying to share media.
It forces the user to share media from third party apps to Signal but Signal itself takes too long to show a media picker.
Screenshots
No response
Device
Pixel 9a
Android version
Android 16
Signal version
7.70.1
Link to debug log
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading MediaRepository.getMediaInBucket() and MediaGalleryViewModel.loadItemsForBucket(), then reproduce the delay with a large media library. Trace the two queries, list merge, sort, and ViewModel handoff described in the issue. Done means the gallery shows recent items quickly and continues loading more as the user scrolls without blocking the UI.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, java, kotlin
- Domain
- mobile, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100