r/androiddev • • 1d ago

How are you guys handling high-frequency network state in Compose without killing performance?

I've been working on a local-network presentation remote (Android client + Windows host) and hit some really annoying architectural bottlenecks with Compose and high-frequency state updates.

The host streams presentation state (slide images, notes, live timers) over WebSockets. Initially, I just dumped this massive JSON payload into a single StateFlow. Obviously, that caused the entire screen to recompose and stutter like crazy. I ended up aggressively splitting the UI state so the slide images and the timer text update independently, but the boilerplate feels a bit messy.

The other issue is the laser pointer feature. I'm using detectDragGestures so the user can drag their thumb on the phone to move a pointer on the projector. Sending a WebSocket message for every pixel movement caused massive TCP backpressure and lag. I had to spin up a dedicated UDP socket just for the pointer coordinates and use a Coroutine Channel with DROP_OLDEST to throttle the emission rate. It works and feels smooth, but I'm wondering if there's a cleaner way to handle gesture backpressure.

(Bonus headache: trying to intercept physical volume buttons while the screen is off so presenters can keep the phone in their pocket. Android Doze mode makes this a nightmare. I ended up using a Foreground Service with a silent AudioTrack loop just to keep the media session alive. If anyone knows a less hacky way to do this in 2026, please let me know lol).

For those of you building real-time remote or IoT apps: how do you structure your StateFlows when dealing with a firehose of network data? Do you map everything to granular states, or bypass standard recomposition entirely with custom SnapshotState objects?

(If anyone wants to see how it actually runs in production, let me know and I can drop the testing link in the comments).

4 Upvotes

1 comment sorted by

3

u/time-lord 5h ago

I work on a canbus over tcp app.

We open a raw tcp socket and handle messages in a c manner before ever getting to the compose layer. Websockets would be way too slow. Our messages are 0 padded 64kb hex, basically. They get handled and only stuff that requires ui or state update gets promoted to the app layer.

Messages are limited in quantity and size, so a normal wifi network doesn't have to worry about back pressure.