signalapp / signalapp/Signal-Android

Media picker extremely slow to open on devices with large photo libraries (50k+ items)

Open
#14,566 5 comments 1 reaction 0 assignees View on GitHub

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

  1. Use a device with a large media library (50,000+ photos/videos)
  2. Open any conversation in Signal
  3. Tap the attachment button and select the gallery
  4. 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:

  1. No pagination: MediaRepository.getMediaInBucket() filters by folder ("bucket") but loads all items within that folder without a LIMIT clause. When "All Media" is selected, the folder filter is removed and it returns every photo/video on the device.

  2. Massive object allocations: Each of 100k rows creates Media, Uri, and String objects—hundreds of thousands of allocations causing GC pressure.

  3. Two queries + in-memory merge + sort: Images and videos are fetched separately, merged, then sorted in memory with Collections.sort().

  4. 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

Suggested Fix

  1. Implement pagination (Paging3 or LIMIT/OFFSET queries)
  2. Load only the first 200–500 items for fast initial render
  3. Load more items on scroll
  4. Consider MediaStore.Files with 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.