Kotlin Multiplatform: nó là gì, shared module và expect/actual

Tác giả: IT Sectr Đã đăng: 2026-02-11 Thời gian đọc: 11 phút

Kotlin Multiplatform (KMP) là công nghệ của JetBrains biên dịch mã Kotlin dùng chung cho iOS, Android, Web và Desktop. Không giống như Flutter và React Native, KMP không thay thế UI gốc — logic dùng chung được trích xuất vào shared module, trong khi giao diện của mỗi ứng dụng vẫn là gốc. Kotlin Multiplatform documentation — tài liệu tham khảo chính để cấu hình module và cơ chế expect/actual.

Những điểm chính

  • KMP — logic dùng chung trong Kotlin với expect/actual cho API nền tảng mà không thay thế UI gốc
  • Shared module — module Gradle chứa mã mạng, cơ sở dữ liệu, xác thực và logic nghiệp vụ cho tất cả nền tảng
  • Expect/actual — cơ chế khai báo API nền tảng trong mã dùng chung với triển khai cho từng mục tiêu
  • Tích hợp iOS — shared module được biên dịch thành framework Apple qua Kotlin/Native
  • KMP vs KMM — Kotlin Multiplatform Mobile (tập trung di động) hiện là một phần của Kotlin Multiplatform

Kotlin Multiplatform là gì?

Kotlin Multiplatform là công nghệ biên dịch chéo cho phép viết mã dùng chung trong Kotlin và biên dịch nó cho nhiều nền tảng khác nhau: JVM (Android), LLVM (iOS, macOS, watchOS), JavaScript (Web) và tệp nhị phân gốc (Linux, Windows). KMP không phải là framework UI — nó giải quyết vấn đề tái sử dụng logic nghiệp vụ, không phải giao diện.

Kiến trúc KMP được xây dựng xung quanh một shared module — module Gradle chứa commonMain với mã độc lập nền tảng và source sets cho mỗi mục tiêu (androidMain, iosMain, desktopMain). Theo dữ liệu của JetBrains năm 2025, hơn 40% dự án Kotlin mới sử dụng KMP để chia sẻ mã giữa các nền tảng.

Kotlin Multiplatform Mobile (KMM) — tên trước đây cho kịch bản di động iOS+Android. Từ Kotlin 2.1+, thuật ngữ KMM đã được thay thế bằng Kotlin Multiplatform, vì công nghệ đã vượt ra ngoài phát triển di động. Netflix, McDonald's và VMware sử dụng KMP trong sản xuất để chia sẻ mã giữa các ứng dụng di động.

Cơ chế expect/actual: kiến trúc

Expect/actual — cơ chế chính của KMP để làm việc với mã dành riêng cho nền tảng. Trong commonMain, một khai báo expect (hàm, lớp, thuộc tính) được khai báo và trong mỗi source set dành riêng cho nền tảng (androidMain, iosMain), một triển khai actual được cung cấp. Trình biên dịch kiểm tra rằng với mỗi expect có một actual trên mỗi nền tảng mục tiêu.

kotlin
// commonMain — khai báo API nền tảng
expect fun getPlatformName(): String

expect class PlatformContext(val appVersion: String)

// androidMain — actual cho Android
actual fun getPlatformName(): String = "Android \${Build.VERSION.SDK_INT}"

// iosMain — actual cho iOS
actual fun getPlatformName(): String =
    UIDevice.currentDevice.systemName

Phân cấp source sets trong KMP cho phép tạo các cấp trung gian: ví dụ: iosArm64Main (thiết bị iOS vật lý) và iosSimulatorArm64Main (trình mô phỏng) với iosMain dùng chung. Mã từ commonMain có sẵn cho tất cả nền tảng, trong khi mã từ iosMain chỉ có sẵn cho các mục tiêu iOS. Điều này giảm trùng lặp khi việc triển khai khác nhau không phải cho từng nền tảng mà cho một nhóm nền tảng.

Trong thực tế, expect/actual được sử dụng để: truy cập bộ nhớ cục bộ (SharedPreferences vs NSUserDefaults), mạng (HttpEngine theo nền tảng), truy cập hệ thống tệp, mật mã và phân tích. JetBrains khuyến nghị giảm thiểu số lượng khai báo expect/actual và chuyển càng nhiều mã càng tốt vào commonMain.

Shared module: cấu trúc và Gradle

Shared module — module Gradle tiêu chuẩn với plugin org.jetbrains.kotlin.multiplatform. Nó chứa mã dùng chung trong src/commonMain/kotlin/ và triển khai dành riêng cho nền tảng trong src/androidMain/kotlin/src/iosMain/kotlin/. Một dự án KMP cũng bao gồm androidAppiosApp, phụ thuộc vào shared module.

kotlin
// build.gradle.kts — shared module
plugins {
    kotlin("multiplatform")
    id("com.android.library")
}

kotlin {
    androidTarget()
    
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach {
        it.binaries.framework {
            baseName = "shared"
            isStatic = true
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-core:3.1.0")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-okhttp:3.1.0")
            }
        }
        val iosMain by creating {
            dependencies {
                implementation("io.ktor:ktor-client-darwin:3.1.0")
            }
        }
    }
}

Cấu hình Gradle cho KMP yêu cầu khai báo rõ ràng các mục tiêu iOS — x64 (trình mô phỏng Intel), arm64 (thiết bị vật lý) và simulatorArm64 (trình mô phỏng Apple Silicon). Một framework Apple riêng biệt được tạo cho mỗi mục tiêu. Plugin kotlin("multiplatform") tự động cấu hình biên dịch cho JVM và LLVM tùy theo các mục tiêu đã khai báo.

Ktorkotlinx.serialization — các thư viện KMP tiêu chuẩn hỗ trợ mã dùng chung. Ktor cung cấp máy khách HTTP với các engine cho mỗi nền tảng (OkHttp cho Android, Darwin cho iOS). kotlinx.serialization hoạt động trên tất cả nền tảng mà không cần expect/actual nhờ triển khai đa nền tảng trong commonMain.

Tích hợp iOS qua Kotlin/Native

Kotlin/Native — trình biên dịch Kotlin cho mã gốc qua LLVM. Đối với iOS, shared module được biên dịch thành framework Apple (.framework) được kết nối qua Xcode. Việc gọi mã dùng chung từ Swift/Objective-C diễn ra thông qua các tiêu đề Objective-C được tạo, do đó API của shared module phải tương thích với Objective-C.

Giới hạn tích hợp iOS: các collection Kotlin (List, Map) được chuyển đổi thành NSArray/NSDictionary. Các hàm có tham số mặc định không được xuất — cần overloads. Đối với các hàm suspend, các phương thức dựa trên callback được tạo với @ObjCName và hỗ trợ async/await từ Kotlin 2.0+.

swift
// Ứng dụng iOS: gọi shared module từ Swift
import shared

class ViewModel: ObservableObject {
    let repository = UserRepository()
    
    func loadUsers() {
        repository.fetchUsers(completionHandler: { result, error in
            if let users = result as? [User] {
                print("Users: \(users.count)")
            }
        })
    }
}

Tích hợp shared module vào Xcode diễn ra qua embed-and-framework — .xcframework được tạo sẽ được thêm vào dự án Xcode. Plugin Gradle có thể tự động cập nhật framework trong quá trình xây dựng qua embedAndSignAppleFrameworkForXcode. Để kiểm thử trên trình mô phỏng, tệp nhị phân iosSimulatorArm64 hoặc iosX64 là đủ.

KMP vs Flutter vs React Native

Việc lựa chọn giữa KMP, Flutter và React Native phụ thuộc vào ưu tiên: tái sử dụng mã hay đa nền tảng hoàn toàn. KMP cung cấp UI gốc trên mỗi nền tảng nhưng yêu cầu hai cơ sở mã cho giao diện. Flutter và React Native sử dụng một UI duy nhất nhưng hy sinh tính gốc.

Đặc điểmKMPFlutterReact Native
Framework UIGốc (Android XML/Jetpack Compose + SwiftUI)Dart + trình kết xuất Skia riêngReact + thành phần gốc
Mã dùng chungLogic nghiệp vụ, mạng, DB, xác thực100% trừ plugin gốc100% trừ module gốc
Hiệu suấtGốc (không có lớp trung gian)Cao (Skia Engine)Trung bình (JSI Bridge)
Hỗ trợ iOSKotlin/Native (xuất sắc)Xuất sắcTốt
Rào cản gia nhậpTrung bình (Kotlin + nền tảng gốc)Thấp (một ngôn ngữ + một UI)Thấp (JS/TS + React)

Khi nào chọn KMP: dự án yêu cầu UI hiệu suất cao (trò chơi, bản đồ, hoạt ảnh), cần tái sử dụng mã gốc hiện có, nhóm đã biết Kotlin và các nền tảng gốc. Khi nào chọn Flutter/RN: MVP hoặc startup với ngân sách hạn chế, nhóm một hồ sơ, UI không yêu cầu tùy chỉnh gốc sâu.

Công cụ và thư viện KMP

Hệ sinh thái công cụ KMP bao gồm các thư viện cho tất cả các lớp ứng dụng: mạng (Ktor), tuần tự hóa (kotlinx.serialization), cơ sở dữ liệu (SQLDelight), điều hướng (Decompose), DI (Koin) và lưu trữ dữ liệu (multiplatform-settings). JetBrains hỗ trợ Compose Multiplatform — framework UI bằng Kotlin hoạt động trên tất cả nền tảng.

kotlin
// Kho lưu trữ KMP với SQLDelight + Ktor
class UserRepository(
    private val httpClient: HttpClient,
    private val db: AppDatabase
) {
    suspend fun syncUsers(): List<User> {
        val remote = httpClient.get("https://api.example.com/users")
            .body<List<UserDto>>()
        
        db.userQueries.replaceAll(remote.map { it.toDomain() })
        
        return db.userQueries.selectAll().executeAsList()
    }
}

Compose Multiplatform — framework UI cho KMP dựa trên Jetpack Compose. Nó cho phép viết giao diện bằng Kotlin cho Android, iOS, Desktop và Web. Vào năm 2025, Compose Multiplatform đã đạt trạng thái ổn định cho Android và Desktop; mục tiêu iOS đang ở giai đoạn beta. Đối với các dự án sản xuất với UI gốc, lợi thế của KMP vẫn là điểm khác biệt chính so với Flutter.

Câu hỏi thường gặp

Kotlin Multiplatform khác Kotlin Multiplatform Mobile như thế nào?

KMM — kịch bản di động của KMP cho iOS và Android. Từ Kotlin 2.1+, JetBrains đã kết hợp cả hai thuật ngữ thành Kotlin Multiplatform, vì công nghệ hỗ trợ không chỉ các nền tảng di động mà còn Desktop và Web. Các dự án KMM tiếp tục hoạt động, nhưng hiện là một phần của KMP tổng thể.

Có thể sử dụng KMP với SwiftUI không?

Có. KMP được biên dịch thành framework Apple qua Kotlin/Native với tiêu đề Objective-C. SwiftUI nhập framework này như bất kỳ thư viện thông thường nào. Shared module xuất các lớp và hàm Kotlin được gọi từ Swift với một số hạn chế (ví dụ: collection Kotlin được chuyển đổi thành kiểu Foundation).

Làm thế nào để kiểm thử shared module trên iOS?

Trên iOS, shared module được kiểm thử qua kiểm thử Kotlin/Native trong source set iosTest. Đối với kiểm thử UI, XCTest được sử dụng trong Xcode với framework đã nhập. Kiểm thử Kotlin được viết trong commonTest với kotlin.test và chạy trên trình mô phỏng iOS qua tác vụ Gradle iosSimulatorArm64Test.

Những thư viện nào có sẵn trong KMP?

Các thư viện KMP chính: Ktor (mạng), kotlinx.serialization (JSON), SQLDelight (DB), Koin (DI), Decompose (điều hướng), multiplatform-settings (SharedPreferences/NSUserDefaults), Apollo GraphQL, Firebase (qua KMP-NativeCoroutines). Compose Multiplatform cung cấp UI cho tất cả nền tảng.

KMP có hỗ trợ Gradle 8 không?

Có. KMP hoàn toàn tương thích với Gradle 8.5+. Bắt đầu từ Kotlin 2.1, các plugin chính thức hỗ trợ Gradle 8. Cấu hình qua build.gradle.kts với kotlin("multiplatform") yêu cầu Gradle 7.6+, nhưng phiên bản 8.5 được khuyến nghị cho hiệu suất xây dựng tối ưu.

Tổng kết

  • Kotlin Multiplatform — công nghệ đa nền tảng của JetBrains cho mã dùng chung mà không thay thế UI gốc
  • Expect/actual — cơ chế khai báo API nền tảng trong commonMain với triển khai cho mỗi mục tiêu
  • Shared module — module Gradle với commonMain và source sets dành riêng cho nền tảng (androidMain, iosMain)
  • Kotlin/Native biên dịch shared module thành framework Apple có thể gọi từ Swift và Objective-C
  • KMP vs Flutter/RN — tái sử dụng logic + UI gốc so với cơ sở mã đơn và UI
  • Compose Multiplatform — framework UI bằng Kotlin cho Android, iOS, Desktop và Web
  • Hệ sinh thái — Ktor, SQLDelight, Koin, kotlinx.serialization, Decompose cho tất cả lớp ứng dụng

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm