跪拜 Guibai
← All articles
Android

How a Robot Vacuum App Fixed Map Jank, Cache Staleness, and P2P Lag

By Android小渣渣 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Any app that composites a live device feed with cloud-managed configuration hits the same class of bugs: cache staleness after user edits, real-time data clobbering static state, and slow peer-to-peer connections blocking the UI. The three-tier data model here—local cache for instant paint, cloud as the source of truth, P2P as the final correction—is a transferable pattern for IoT, robotics, and smart-home apps.

Summary

The device detail page for TanGe robot vacuums suffered from slow map loads, conflicting loading indicators, and stale caches that caused the map to jump or fail to refresh after a user switched or deleted maps. Path data persisted across app restarts produced jarring trajectory jumps, while forbidden zones appeared noticeably later than the map itself. A rewrite of the caching layer now treats the cloud as the authoritative source, refreshes caches through a single unified entry point after every map management action, and distinguishes between stable configuration data (forbidden zones, which are cached) and strongly real-time data (paths, which are not).

During cleaning, map management data is blocked from overwriting the live map to prevent visual jumps. Quick-mapping now polls the cloud up to three times instead of firing a single delayed request, and forbidden-zone cache keys bind to both device and map IDs to survive multi-map setups. The team also removed a 5-second request throttle that dropped map and path data when users rapidly toggled between the device list and the detail page.

The broader P2P connection strategy layers local cache, cloud map management data, and real-time device reports so the UI never waits on a slow peer-to-peer link. Pre-connection, short-term keep-alive, a connection state machine, and LAN-first relay fallback are all on the table, though the SDK's three-device pre-connect limit constrains the first option.

Takeaways
Map cache is now invalidated through a single reloadCurrentUsedMapCache() entry point, eliminating scattered cache-clearing logic that missed edge cases.
During active cleaning, map management data is prevented from overwriting the live currentMap to stop map flicker.
Path data is no longer persisted to disk; it lives only in process memory to prevent trajectory jumps when the app restarts.
Forbidden zones are cached with a key that binds deviceId and mapId, and restoration uses synchronous value assignment instead of postValue() to close the timing gap with the map.
Quick-mapping success now triggers a polling loop (every 5 seconds, up to 3 times) instead of a single delayed fetch, because the cloud map may not be ready when the command ACK arrives.
The 5-second request throttle that dropped map and path data during rapid list-to-detail switching was removed; every entry now requests full data.
First-time entry shows the operation guide before the detail-page loading indicator, and subsequent entries skip the GIF loading entirely.
Cloud data is the authoritative cache source: getMultiMapsFromCloud() writes the cache when a current map exists and clears it when none does.
A three-layer data strategy is recommended: local cache for instant display, cloud map management data for recovery, and P2P real-time reports as the final correction.
Conclusions

Distinguishing configuration data from real-time data is the core design decision that makes or breaks an IoT cache layer; forbidden zones are stable enough to cache, paths are not.

Unifying cache invalidation into a single method call is a low-cost change that eliminates an entire class of stale-data bugs caused by scattered cache writes.

Blocking map management data from updating the live map during cleaning is a state-aware guard that many apps miss, leading to the classic 'map jumps while the robot is running' complaint.

The quick-mapping polling fix highlights a common IoT trap: treating a command ACK as proof that the cloud side-effect has completed.

Removing the 5-second request throttle trades a bit of network load for correctness; the original throttle was a premature optimization that caused visible data loss.

Binding forbidden-zone cache keys to mapId is forward-looking even if the current device treats zones as global, because multi-map support inevitably arrives.

The P2P pre-connect limit of three devices is a hard SDK constraint that forces a trade-off between connection speed and device resource pressure.

Concepts & terms
Three-tier IoT data model
A pattern where local cache provides instant display, cloud data serves as the authoritative configuration source, and real-time device (P2P) reports act as the final correction layer.
P2P connection state machine
A unified state manager (Idle, Connecting, Connected, Failed, Retrying, Disconnected) that prevents duplicate connect calls, coordinates foreground/background transitions, and applies retry backoff.
Quick-mapping polling
Instead of a single delayed cloud fetch after a quick-map command ACK, the client polls every 5 seconds (up to 3 times) until the map count or current mapId changes, because cloud map generation is asynchronous.
Cache invalidation entry point
A single method (reloadCurrentUsedMapCache) that clears the local cache and re-fetches from the cloud, called by every map mutation path to prevent stale reads.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗