The 120Hz Trap: Debugging Infinite Recomposition and Silent Deep Link Failures on ColorOS
How high refresh rates and deep link failures were resolved.
1Introduction
As Android developers transition to declarative UIs with Jetpack Compose, device-specific quirks can expose hidden bugs in 'stable' code. A critical incident on the Oppo F31 Pro 5G exemplified this.
2120Hz and the Recomposition Loop
The Oppo F31 Pro's 120Hz display ruthlessly exposed state management mistakes in Compose. Code that ran smoothly on 60Hz devices caused severe flickering and infinite loading states at 120Hz.
3Cause of the Recomposition Loop
High refresh rate displays don't create recomposition bugs. Writing to MutableState during the composition phase does. This loop exists on 60Hz devices too, but is less noticeable.
4Solution: State Mutations
The bug was fixed by moving state mutations out of direct @Composable scope into lifecycle-aware blocks. This broke the recomposition loop and ensured smooth screen operation.
5Deep Link Failure
On the Oppo F31 Pro, the 'Pay Now' deep link died silently. Clicking it did nothing, and the page got stuck. This issue was caused by package visibility filtering introduced in Android 11.
6Package Visibility Filtering
Since Android 11, apps can no longer see the full list of installed packages. Without a queries block in the manifest, resolveActivity() calls return null, preventing the target app from launching.
7Solution and Conclusion
The issue was resolved by declaring a queries block in the manifest and making intent routing genuinely defensive. This ensured deep links worked reliably.
Original article: ProAndroidDev - Medium — Oppo F31 Pro'da 120Hz ve Deep Link Sorunları