⚡ perf: optimize GPX export threading to prevent UI freezing#28
Conversation
- Moved FileOutputStream writing to Dispatchers.IO in TrackingScreen.kt and HistoryScreen.kt - Moved CPU-intensive GpxGenerator.generateGpx to Dispatchers.Default in both screens - Added benchmark test to verify execution context and time improvements Co-authored-by: Max97k <14903047+Max97k@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
There was a problem hiding this comment.
Code Review
This pull request improves UI responsiveness by offloading GPX generation to Dispatchers.Default and file export operations to Dispatchers.IO in both HistoryScreen and TrackingScreen. It also introduces a benchmark test to measure GPX export performance. Feedback is provided to optimize memory usage during file writing by using a bufferedWriter instead of allocating a large byte array, and to ensure temporary files created during benchmark tests are properly cleaned up.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| FileOutputStream(targetFile).use { | ||
| it.write(gpxContent.toByteArray()) | ||
| } |
There was a problem hiding this comment.
Converting the entire GPX string to a byte array using gpxContent.toByteArray() allocates a large byte array in memory (e.g., 10MB+ for long tracking sessions). This can cause significant memory pressure and potential OutOfMemoryError crashes on memory-constrained Android devices. Instead, write the string directly to the file using a BufferedWriter via bufferedWriter(), which encodes and writes the characters in chunks without allocating the entire byte array at once.
| FileOutputStream(targetFile).use { | |
| it.write(gpxContent.toByteArray()) | |
| } | |
| targetFile.bufferedWriter().use { | |
| it.write(gpxContent) | |
| } |
| println("Note: The primary improvement is moving off the Main thread, not necessarily reducing raw I/O time. Blocking the Main thread causes UI freezes.") | ||
| } |
There was a problem hiding this comment.
The benchmark creates a 10MB temporary file using File.createTempFile but never deletes it. This will leak large files in the system's temporary directory every time the tests are run. Clean up the temporary file at the end of the benchmark.
println("Note: The primary improvement is moving off the Main thread, not necessarily reducing raw I/O time. Blocking the Main thread causes UI freezes.")
tempFile.delete()
}
💡 What:
TrackingScreen.ktandHistoryScreen.ktto wrap synchronousFileOutputStreamoperations inwithContext(Dispatchers.IO).GpxGenerator.generateGpxoperations inwithContext(Dispatchers.Default).🎯 Why:
The GPX export functionality was previously executing on the main thread. Writing large files (I/O) and generating large XML strings (CPU) synchronously blocks the main UI thread, causing UI freezes, lag, and potentially Application Not Responding (ANR) crashes for users when exporting long tracking sessions.
📊 Measured Improvement:
Added
GpxExportBenchmarkTest.ktto measure the execution.Dispatchers.IOcontext switch): ~277msWhile the raw wall-clock time is similar, the critical improvement is that these operations are completely offloaded from the Main thread to
Dispatchers.IOandDispatchers.Default, freeing up the UI thread and preventing freezes.PR created automatically by Jules for task 9852801055414253535 started by @Max97k