Skip to content

Fix XML image flicker caused by interceptorCoroutineContext(Dispatchers.IO)#6284

Merged
VelikovPetar merged 1 commit intodevelopfrom
bug/fix_xml_avatar_flicker
Mar 23, 2026
Merged

Fix XML image flicker caused by interceptorCoroutineContext(Dispatchers.IO)#6284
VelikovPetar merged 1 commit intodevelopfrom
bug/fix_xml_avatar_flicker

Conversation

@VelikovPetar
Copy link
Copy Markdown
Contributor

@VelikovPetar VelikovPetar commented Mar 23, 2026

Goal

Fix image flickering (placeholder briefly appearing before cached image) in the XML/View SDK.

Implementation

Removed .interceptorCoroutineContext(Dispatchers.IO) from StreamImageLoaderFactory.

Setting this to Dispatchers.IO forced Coil's entire interceptor chain — including the memory cache lookup — to run on a background thread. For ImageView.load(), this meant a Main → IO → Main thread hop even for memory-cached images, causing a brief placeholder flash on every rebind.

Coil's default (Main.immediate) allows synchronous memory cache hits with zero placeholder flash. The actual network/disk fetching still happens on background threads regardless of this setting.

The ImageHeadersInterceptor (Compose SDK) is unaffected — it already does its own withContext(Dispatchers.IO) internally.

Also cleaned up unused imports (OkHttpNetworkFetcherFactory, okhttp3.Dispatcher, OkHttpClient, kotlinx.coroutines.Dispatchers).

UI Changes

No UI changes (fixes a visual regression — placeholder no longer flashes for cached images).

Testing

  • Load a channel list or message list with avatars/image attachments in the XML SDK
  • Scroll away and back — images should appear instantly from cache without placeholder flash
  • Verify Compose SDK image loading is unaffected

Summary by CodeRabbit

  • Refactor
    • Optimized image loading performance by adjusting internal dispatcher configuration.

…hers.IO)

Co-Authored-By: Claude <noreply@anthropic.com>
@VelikovPetar VelikovPetar added the pr:bug Bug fix label Mar 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 23, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@github-actions
Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.26 MB 5.26 MB 0.00 MB 🟢
stream-chat-android-offline 5.49 MB 5.49 MB 0.00 MB 🟢
stream-chat-android-ui-components 10.63 MB 10.63 MB -0.00 MB 🚀
stream-chat-android-compose 12.85 MB 12.86 MB 0.00 MB 🟢

@VelikovPetar VelikovPetar marked this pull request as ready for review March 23, 2026 17:00
@VelikovPetar VelikovPetar requested a review from a team as a code owner March 23, 2026 17:00
@sonarqubecloud
Copy link
Copy Markdown

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 81fd07e9-740a-4bf4-8c54-12c4654247a8

📥 Commits

Reviewing files that changed from the base of the PR and between 13e5f79 and 5683451.

📒 Files selected for processing (1)
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/StreamImageLoaderFactory.kt
💤 Files with no reviewable changes (1)
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/StreamImageLoaderFactory.kt

Walkthrough

Removed the explicit Coil interceptorCoroutineContext(Dispatchers.IO) configuration from the StreamImageLoaderFactory's ImageLoader.Builder setup, allowing interceptors to use their default coroutine context instead of forcing execution on the IO dispatcher.

Changes

Cohort / File(s) Summary
Coil Configuration
stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/StreamImageLoaderFactory.kt
Removed explicit interceptorCoroutineContext(Dispatchers.IO) configuration from ImageLoader.Builder, eliminating forced IO dispatcher usage for interceptor coroutine execution.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐰 A dispatcher once bound in chains so tight,
Now floats freely, light as morning light,
IO no more, let Coil find its way,
Simpler flows make for a better day! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title precisely captures the main change: removing interceptorCoroutineContext(Dispatchers.IO) to fix XML image flickering caused by unnecessary thread hops.
Description check ✅ Passed The description covers Goal, Implementation, UI Changes, and Testing sections from the template. It clearly explains the technical root cause, impact, and testing approach.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bug/fix_xml_avatar_flicker

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@VelikovPetar VelikovPetar enabled auto-merge (squash) March 23, 2026 17:18
@VelikovPetar VelikovPetar merged commit 6c61cbd into develop Mar 23, 2026
20 of 22 checks passed
@VelikovPetar VelikovPetar deleted the bug/fix_xml_avatar_flicker branch March 23, 2026 17:36
@stream-public-bot stream-public-bot added the released Included in a release label Mar 23, 2026
@stream-public-bot
Copy link
Copy Markdown
Contributor

🚀 Available in v6.35.1

andremion added a commit that referenced this pull request Apr 7, 2026
* Improve `Message.createdLocallyAt` creation logic using estimated server time (#6199)

* Fix createdLocallyAt using NTP-style server clock offset estimation

Co-Authored-By: Claude <noreply@anthropic.com>

* Pr remarks

* Adjust thread message createdLocallyAt.

* Ensure exceedsSyncThreshold is compared against estimated server time (where applicable).

* Add max allowed offset.

---------

Co-authored-by: Claude <noreply@anthropic.com>

* [skip ci] Update SDK sizes

* Update README cover image (#6282)

* Fix XML image flicker caused by `interceptorCoroutineContext(Dispatchers.IO)` (#6284)

Co-authored-by: Claude <noreply@anthropic.com>

* [skip ci] Update SDK sizes

* AUTOMATION: Version Bump

* Fix race condition in plugin resolution during disconnect (#6269)

* Update `DependencyResolverTest` to verify error handling when dependency resolution races with disconnection.

* Prevent race conditions during disconnects in `ChatClient`.

* Handle unresolvable attachments in picker (#6285)

- Update `StorageHelper` and `AttachmentMetaDataMapper` to safely handle cases where content URIs (e.g. cloud-backed files) cannot be opened.
- Introduce `hasUnresolvedAttachments` state in `AttachmentsPickerViewModel` to track failed attachment resolutions.
- Show a toast message in both View-based and Compose attachment pickers when files are unavailable and need to be downloaded to the device.
- Add `clearUnresolvedAttachments` to reset the error state after it has been consumed by the UI.
- Add unit tests for unresolved attachment scenarios in `AttachmentsPickerViewModelTest`.

* [skip ci] Update SDK sizes

* Fix wrong message selected on quoted message long click (#6292)

* Use type-specific attachment URL fields and deprecate `imagePreviewUrl` (#6280)

* Deprecate imagePreviewUrl and use type-specific attachment URL fields

Co-Authored-By: Claude <noreply@anthropic.com>

* Extract common extensions.

---------

Co-authored-by: Claude <noreply@anthropic.com>

* Expose optional completion callback for audio recording (#6290)

Co-authored-by: Claude <noreply@anthropic.com>

* AUTOMATION: Version Bump

* AUTOMATION: Clean Detekt Baseline Files (#6299)

Co-authored-by: adasiewiczr <17440581+adasiewiczr@users.noreply.github.com>

* Add support for intercepting CDN file requests (#6295)

* Add new CDN contract.

* Add CDN for document files.

* Add CDN support for downloading attachments.

* Deprecate current CDN methods.

* Add progress indicator snackbar.

* Add useDocumentGView config flag.

* Add file sharing cache handling.

* Add file sharing cache handling.

* Remove CDNResponse.kt

* Add tests

* PR remarks

* [skip ci] Update SDK sizes

* Post-merge clean-up.

* Post-merge clean-up.

* ApiDump.

* Improve attachment URI resolution and error handling in `AttachmentsPickerViewModel` and `AttachmentStorageHelper`.

- Add `isUriResolvable` to `StorageHelper` to verify if a content URI can be opened for reading.
- Implement `partitionResolvable` in `AttachmentStorageHelper` to separate metadata based on URI accessibility.
- Update `AttachmentsPickerViewModel.resolveAndSubmitUris` to exclude inaccessible URIs (e.g., undownloaded cloud files) from the submission.
- Ensure `hasUnresolvedAttachments` is correctly set when URIs are inaccessible, independent of file type support.
- Add unit tests in `AttachmentStorageHelperTest` and `AttachmentsPickerViewModelTest` to verify partitioning logic and view model state updates.

* Handle unresolvable attachments in XML

* apiDump.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: André Mion <andremion@gmail.com>
Co-authored-by: Gianmarco <47775302+gpunto@users.noreply.github.com>
Co-authored-by: stream-pr-merger[bot] <117762243+stream-pr-merger[bot]@users.noreply.github.com>
Co-authored-by: adasiewiczr <17440581+adasiewiczr@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:bug Bug fix released Included in a release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants