feat(ui): add launchIO helper to BaseViewModel for background operations#128
feat(ui): add launchIO helper to BaseViewModel for background operations#128therajanmaurya wants to merge 1 commit intodevfrom
Conversation
Add a launchIO helper function to BaseViewModel that launches coroutines
on Dispatchers.IO. This prevents UI freezing when performing network or
database operations by ensuring they run on background threads.
Usage:
- Replace `viewModelScope.launch { }` with `launchIO { }` for I/O operations
- StateFlow updates remain thread-safe
- Progress indicators animate smoothly during API calls
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughA new helper function Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~4 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
core-base/ui/src/commonMain/kotlin/template/core/base/ui/BaseViewModel.kt (1)
105-115: KDoc overstates whenDispatchers.IOis required; clarify scope.The comment implies
launchIOshould be used for all "network or database operations", butDispatchers.IOis only needed if you have an API that blocks threads — if you use suspending functions, you can use any dispatcher, and you do not needDispatchers.IOfor network or database libraries that already provide suspending functions.Using
launchIOwith modern suspend-based APIs (Ktor, Room with coroutines, SQLDelight) is harmless but misleading. The KDoc should clarify that this is specifically for blocking I/O calls. Otherwise, developers will cargo-cultlaunchIOfor every use case, including ones whereDispatchers.Defaultor the default scope dispatcher is already correct.📝 Suggested KDoc improvement
- /** - * Launches a coroutine on [Dispatchers.IO] for network or database operations. - * Use this instead of `viewModelScope.launch` for any I/O-bound work to avoid - * blocking the main thread and causing UI freezes. - * - * `@param` block The suspending block to execute on the IO dispatcher. - * `@return` The [Job] representing the coroutine. - */ + /** + * Launches a coroutine on [Dispatchers.IO] for **blocking** I/O operations + * (e.g., legacy blocking network/file APIs, JDBC, or any call that parks the thread). + * + * If you are using suspend-based libraries (Ktor, Room, SQLDelight, etc.), the library + * already dispatches work off the main thread internally; prefer plain `viewModelScope.launch` + * in that case. + * + * Note: unhandled exceptions in the block propagate to the scope's [CoroutineExceptionHandler]. + * + * `@param` block The suspending block to execute on the IO dispatcher. + * `@return` The [Job] representing the coroutine. + */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core-base/ui/src/commonMain/kotlin/template/core/base/ui/BaseViewModel.kt` around lines 105 - 115, Update the KDoc for the protected function launchIO in BaseViewModel to clarify that Dispatchers.IO is intended for blocking I/O operations (e.g., legacy blocking file, socket, or JDBC calls) and not required for modern suspending I/O libraries (e.g., Ktor, Room with coroutines, SQLDelight) that are already non-blocking; mention that using launchIO with suspending APIs is harmless but unnecessary and recommend using the default viewModelScope dispatcher or Dispatchers.Default for CPU-bound work or when the API is already suspend-friendly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@core-base/ui/src/commonMain/kotlin/template/core/base/ui/BaseViewModel.kt`:
- Around line 105-115: Update the KDoc for the protected function launchIO in
BaseViewModel to clarify that Dispatchers.IO is intended for blocking I/O
operations (e.g., legacy blocking file, socket, or JDBC calls) and not required
for modern suspending I/O libraries (e.g., Ktor, Room with coroutines,
SQLDelight) that are already non-blocking; mention that using launchIO with
suspending APIs is harmless but unnecessary and recommend using the default
viewModelScope dispatcher or Dispatchers.Default for CPU-bound work or when the
API is already suspend-friendly.
|
Closing to create a new PR with the fix for Dispatchers.IO multiplatform compatibility issue. |
…rt (openMF#128) - Add `KMPSQLDelightConventionPlugin` to manage SQLDelight configuration across platforms. - Implement platform-specific `SqlDriver` setups for Android, iOS (Native), Desktop (SQLite), and Web (JS/Wasm). - Introduce `MifosSQLDatabaseInitializer` to handle asynchronous schema creation. - Add `SampleRepository` and `SQLDelightSampleRepositoryImpl` to demonstrate database operations. - Update `DatabaseModule` and `DataModule` to include SQLDelight dependencies via Koin. - Configure Web workers and `sql.js` for JS/Wasm support in `cmp-web`. - Upgrade Gradle wrapper to version 9.1.0 and update project dependencies.
…tform configuration (openMF#128) * Add `SQLDelightRepositoryTest` common base class and platform-specific test implementations for Android, Desktop, Native, JS, and WasmJs. * Update `testSQLDelightPlatformModule` across all platforms to use `single` instances for `SqlDriver` and ensure proper schema initialization. * Refactor Koin module organization by moving `TestDatabaseModule` to `nonJsCommonTest` and removing the `DatabaseModule` include from `DataModule`. * Update Android and Native test modules to use `Dispatchers.IO` directly for Room query contexts. * Enhance JS/WasmJs test infrastructure with `karma.config.d` and `webpack.config.d` for `sql.js` WASM support. * Enable browser testing for JS and WasmJs in `build.gradle.kts` with automatic browser detection. * Update `libs.versions.toml` with `androidx-core` and `core-ktx` dependencies.
Summary
launchIOhelper function toBaseViewModelthat launches coroutines onDispatchers.IOProblem
When using
viewModelScope.launch { }without specifying a dispatcher, coroutines run onDispatchers.Mainby default. This causes the UI to freeze while waiting for API responses, even if the repository layer useswithContext(Dispatchers.IO), because the coroutine resumes on the Main thread.Solution
Add a
launchIOhelper function that all ViewModels inheriting fromBaseViewModelcan use:Usage
Replace:
viewModelScope.launch { val result = repository.makeApiCall() // UI frozen while waiting }With:
launchIO { val result = repository.makeApiCall() // Runs on IO thread, UI stays responsive }Why This Works
StateFlow.update {}is thread-safe and can be called from any threadcollectAsStateWithLifecycle()automatically observes on Main threadTest plan
launchIOfor I/O operations🤖 Generated with Claude Code
Summary by CodeRabbit
Note: This release contains no user-visible changes. Updates are limited to internal code improvements.