如何开发面向iOS和Android的跨平台Kotlin Common模块?
Great question—building stable cross-platform code with Kotlin Multiplatform (KMP) while navigating platform-specific threading differences is a common hurdle, but totally solvable with the right patterns and abstractions. Let’s break this down step by step:
Forget manually managing Worker Threads on iOS and coroutines on Android—Kotlin’s official kotlinx-coroutines-core library provides a unified concurrency API that adapts automatically to each platform. This is the foundation of stable cross-platform threading.
How it works under the hood:
- On Android (JVM), coroutines use familiar dispatchers like
Dispatchers.Main(tied to the main looper) andDispatchers.Default(backed by a thread pool). - On iOS (Kotlin/Native), coroutines map to platform-native constructs:
Dispatchers.Mainbinds to iOS’sDispatchQueue.main, and background dispatchers useWorkerthreads under the hood—no manual Worker setup required.
Example Common Module Code:
// Common code (shared between Android and iOS) import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.withContext class DataRepository { // Fetch data in the background, auto-adapts to platform threads suspend fun fetchRemoteData(): String { return withContext(Dispatchers.Default) { // Simulate a network call (use delay instead of Thread.sleep for coroutine-friendliness) delay(1000) "Cross-platform data loaded successfully" } } // Update UI on the main thread, works on both platforms suspend fun updateUIFromData(data: String) { withContext(Dispatchers.Main) { // This code runs on Android's main looper or iOS's main queue println("Updating UI with: $data") } } }
If you absolutely need to use platform-specific threading logic (e.g., a native iOS API that requires a custom Worker), use KMP’s expect/actual mechanism to abstract the implementation away from your common code.
Example:
// Common code: Define the abstract function expect fun runOnCustomBackgroundThread(block: () -> Unit) // Android (JVM) implementation actual fun runOnCustomBackgroundThread(block: () -> Unit) { Thread(block).start() } // iOS (Native) implementation actual fun runOnCustomBackgroundThread(block: () -> Unit) { // Use Kotlin/Native's Worker API directly here Worker.start().execute(TransferMode.SAFE, { block }) { it() } }
Your common code only calls runOnCustomBackgroundThread()—it never needs to know how each platform handles the thread.
Beyond threading, these practices will keep your common code reliable across both platforms:
- Stick to KMP-official libraries: Use
kotlinx-*libraries (likekotlinx-serializationfor parsing,kotlinx-datetimefor date handling) — they’re rigorously tested for cross-platform compatibility. - Avoid platform-specific APIs in common code: Never reference
android.os.*orkotlin.native.concurrentdirectly in your shared module. Useexpect/actualfor any platform-specific functionality (file access, sensors, etc.). - Write cross-platform tests: Use
kotlin.testto write unit tests in your common module, then run them on both Android (JVM) and iOS (Native) to ensure consistent behavior. Example:// Common test code import kotlin.test.Test import kotlin.test.assertEquals import kotlinx.coroutines.runTest class DataRepositoryTest { private val repo = DataRepository() @Test fun `fetch data returns expected result`() = runTest { val result = repo.fetchRemoteData() assertEquals("Cross-platform data loaded successfully", result) } } - Follow Kotlin/Native memory safety rules: If you need to share state across threads in iOS, use immutable data structures or
@SharedImmutableannotations. Prefer structured concurrency (usingcoroutineScopeor platform-specific scopes likeviewModelScopeon Android) to avoid memory leaks.
Kotlin/Native has come a long way from its early days—modern KMP with coroutines provides a seamless cross-platform concurrency model. By focusing on abstractions over platform-specific implementations, you can write code that runs reliably on both Android and iOS without compromising on performance or stability.
内容的提问来源于stack exchange,提问作者SomethingsGottaGive

