Đặc thù Kotlin trong phát triển di động: nó là gì, những cấu trúc nào và cách hoạt động

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

Kotlin là ngôn ngữ chính để phát triển Android. Theo Google Android Docs (2025), hơn 95% dự án Android mới sử dụng Kotlin. Hiểu đặc thù của Kotlin — data class, sealed class, coroutines và scope functions — là yêu cầu bắt buộc đối với nhà phát triển Android.

Những Điểm Chính

  • data class — tự động tạo equals/hashCode/toString/copy/componentN. Cho mô hình dữ liệu. sealed class — hệ thống phân cấp kiểu bị giới hạn với kiểm tra when.
  • Scope functions: let, run, with, apply, also. Phân biệt bởi ngữ cảnh (it vs this) và giá trị trả về.
  • Coroutines: launch (fire-and-forget), async (có kết quả), runBlocking (cầu nối), withContext (chuyển Dispatcher).
  • lifecycleScopeviewModelScope — coroutine Lifecycle-aware không cần hủy thủ công.
  • reified — bảo toàn kiểu trong hàm inline. lateinit/lazy — khởi tạo trễ.

Lớp (data class, sealed class, object, companion object)

Kotlin mở rộng khái niệm lớp từ Java. data class, sealed class, object và companion object — những cấu trúc không có trong Java hoặc được triển khai khác.

data class vs sealed class

data class — lớp tự động tạo equals(), hashCode(), toString(), copy() và componentN(). Lý tưởng cho mô hình dữ liệu (DTO, Entity). Yêu cầu: ít nhất một tham số trong hàm tạo chính, val/var, không thể là open/sealed/inner. sealed class — lớp có hệ thống phân cấp lớp con bị giới hạn. Tất cả lớp con được biết tại thời điểm biên dịch và khai báo trong cùng tệp. Biểu thức when với sealed class không yêu cầu nhánh else. sealed interface (Kotlin 1.9+) — giống sealed class nhưng cho phép đa kế thừa. object — singleton, khai báo bằng từ khóa object (không phải class). Khởi tạo lười an toàn luồng. companion object — thành viên tĩnh của lớp. Có tên (mặc định là Companion). Có thể triển khai interface và có extension functions.

Loại Mô tả Sử dụng
data classTự động tạo equals, hashCode, toString, copyMô hình dữ liệu, DTO, Entity
sealed classPhân cấp bị giới hạn, kiểm tra whenTrạng thái, Kết quả, UI State
sealed interfacesealed class + đa kế thừaSự kiện, Hành động (Kotlin 1.9+)
objectSingleton (khai báo)Factory, Utility, Hằng số
companion objectThành viên tĩnh của lớpFactory Method, hằng số tĩnh
enum classLiệt kê với hằng sốTrạng thái với tập cố định

data class — cho 90% mô hình. sealed class — cho UI State và Kết quả. object — cho singleton. IT Sectr khuyên dùng sealed class cho tất cả trạng thái màn hình (Loading, Success, Error).

Sealed class trong thực tế

Sealed class — công cụ mạnh mẽ để mô hình hóa trạng thái. Ví dụ: UiState<T> với các lớp con Loading, Success(data: T), Error(message: String). Biểu thức when đảm bảo xử lý tất cả trạng thái. Sealed interface — cho sự kiện và hành động cần triển khai đa lớp. Value class (Kotlin 1.5+) — trình bao bọc cho một giá trị duy nhất không có overhead. Dùng cho định danh an toàn kiểu: @JvmInline value class UserId(val id: String).

Hàm (extension, inline, higher-order, scope functions)

Extension Function — thêm phương thức vào lớp hiện có mà không cần kế thừa. fun String.isEmail(): Boolean. Extension Property — tương tự cho thuộc tính (không có backing field). Inline Function — chèn thân hàm tại vị trí gọi — không có overhead gọi. Dùng cho higher-order functions với lambda. Higher-Order Function — hàm nhận hoặc trả về hàm khác. Scope Functions — năm hàm để làm việc với ngữ cảnh đối tượng: let, run, with, apply, also.

Scope Functions

let — ngữ cảnh it, trả về kết quả lambda. Dùng cho gọi null-safe (?.let {}). apply — ngữ cảnh this, trả về ngữ cảnh. Cho cấu hình đối tượng. run — ngữ cảnh this, trả về kết quả lambda. Cho tính toán với ngữ cảnh. also — ngữ cảnh it, trả về ngữ cảnh. Cho tác dụng phụ (ghi log). with — không phải extension, ngữ cảnh this, trả về kết quả lambda. Cho nhóm thao tác trên đối tượng. Lambda — hàm ẩn danh. Destructuring Declaration — giải nén data class thành biến: val (name, age) = person.

Inline + reified

Inline function với reified — cách duy nhất để bảo toàn kiểu generic trong JVM. Dùng cho: builder an toàn kiểu (Gson.fromJson<T>()), kiểm tra kiểu (is T), lấy lớp (T::class). Crossinline và Noinline — bổ từ cho tham số lambda trong hàm inline. crossinline — cấm non-local return, noinline — cấm inline một lambda cụ thể. IT Sectr khuyên dùng inline + reified chỉ khi làm việc với kiểu; đối với hàm higher-order thông thường, inline có thể tăng kích thước bytecode.

Coroutines (Coroutine Builder, Dispatchers, Scope)

Coroutines — luồng nhẹ cho lập trình bất đồng bộ. Không chặn luồng — tạm dừng (suspend). suspend function — hàm có thể tạm dừng mà không chặn luồng. Chỉ có thể gọi từ coroutine hoặc suspend function khác.

CoroutineScope

CoroutineScope — phạm vi cho coroutines. Chứa CoroutineContext (Job + Dispatcher). lifecycleScope — cho Activity/Fragment (Lifecycle-aware). viewModelScope — cho ViewModel (tự động hủy khi onCleared()). GlobalScope — phạm vi toàn cục (không dùng trong sản phẩm — rò rỉ bộ nhớ). Dispatchers: Dispatchers.Main (UI), Dispatchers.IO (mạng/đĩa), Dispatchers.Default (CPU nhiều), Dispatchers.Unconfined (không khuyến nghị). launch — bắt đầu coroutine: Job. async — bắt đầu với kết quả: Deferred<T>. runBlocking — cầu nối chặn. withContext — chuyển Dispatcher bên trong suspend function.

kotlin
// Ví dụ coroutines: tải dữ liệu trong ViewModel
class MainViewModel : ViewModel() {
    private val _state = MutableStateFlow<UiState>(UiState.Loading)
    val state: StateFlow<UiState> = _state.asStateFlow()

    fun loadData() {
        viewModelScope.launch {
            _state.value = UiState.Loading
            try {
                val data = withContext(Dispatchers.IO) {
                    repository.fetchData()
                }
                _state.value = UiState.Success(data)
            } catch (e: Exception) {
                _state.value = UiState.Error(e.message)
            }
        }
    }
}

// Yêu cầu song song với async
suspend fun loadCombinedData(): CombinedData = coroutineScope {
    val users = async(Dispatchers.IO) { api.getUsers() }
    val posts = async(Dispatchers.IO) { api.getPosts() }
    CombinedData(users.await(), posts.await())
}

viewModelScope.launch — khởi chạy coroutine tiêu chuẩn trong ViewModel. withContext(Dispatchers.IO) — chuyển sang luồng IO cho yêu cầu mạng. Dispatchers xác định coroutine thực thi trên nhóm luồng nào. IT Sectr khuyên dùng viewModelScope cho ViewModel và lifecycleScope cho Activity/Fragment.

Tính năng nâng cao (reified, destructuring, lateinit/lazy)

reified — bổ từ kiểu trong hàm inline. Cho phép sử dụng kiểu: T::class, is T, as T. Không có reified, generic trong JVM bị xóa (type erasure). inline fun + reified — kết hợp mạnh mẽ cho API an toàn kiểu. Destructuring Declaration — val (x, y) = point. Hoạt động cho data class và kiểu có componentN(). typealias — bí danh kiểu: typealias Callback = (String) -> Unit. lateinit — khởi tạo trễ var (cho dependency injection). Không an toàn luồng. lazy — khởi tạo lười val (an toàn luồng mặc định). lazy(LazyThreadSafetyMode.NONE) — không đồng bộ. Extension functionExtension property — thêm chức năng không cần kế thừa. Kotlin là ngôn ngữ nơi extension functions giải quyết 90% tác vụ tiện ích.

Thuộc tính Ủy quyền

Delegated Properties — ủy quyền getter/setter cho đối tượng khác. Người ủy quyền tiêu chuẩn: lazy, observable, vetoable, map. Người ủy quyền tùy chỉnh qua toán tử getValue/setValue. by — từ khóa ủy quyền: val name by lazy { loadName() }. Thuộc tính ủy quyền là nền tảng cho delegate ViewModel (by viewModels()). IT Sectr khuyên dùng lazy cho khởi tạo trễ và Delegates.observable để theo dõi thay đổi.

Tính năng Mô tả Ví dụ
reifiedBảo toàn kiểu generic trong inlineinline fun <reified T> parse(): T
destructuringGiải nén data classval (name, age) = person
typealiasBí danh kiểutypealias Orders = List<Order>
lateinitKhởi tạo trễ varlateinit var adapter: Adapter
lazyKhởi tạo lười valval config by lazy { load() }
delegatedỦy quyền thuộc tínhvar x by Delegates.observable(0)

reified — cho API an toàn kiểu. lazy — cho tải trễ. delegated properties — để tái sử dụng logic thuộc tính. IT Sectr khuyên thành thạo tất cả các tính năng này để phát triển Kotlin hiệu quả.

Flow và StateFlow

Flow — luồng dữ liệu bất đồng bộ lạnh trong Kotlin. Phát giá trị theo yêu cầu của bộ thu. StateFlow — Flow nóng với một giá trị hiện tại duy nhất. Dùng trong ViewModel cho UI State. SharedFlow — Flow nóng cho sự kiện (sự kiện một lần). flowOf, asFlow — tạo Flow từ bộ sưu tập. catch, retry, debounce — toán tử. stateIn, shareIn — chuyển đổi Flow lạnh thành nóng. IT Sectr khuyên dùng StateFlow cho UI State và SharedFlow cho sự kiện (Snackbar, điều hướng).

kotlin
class SearchViewModel : ViewModel() {
    private val _query = MutableStateFlow("")
    val suggestions: StateFlow<List<String>> = _query
        .debounce(300)
        .filter { it.length >= 2 }
        .flatMapLatest { repository.search(it) }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())

    fun onQueryChanged(query: String) {
        _query.value = query
    }
}

Tuần tự hóa (kotlinx.serialization, Parcelize)

kotlinx.serialization — thư viện Kotlin cho tuần tự hóa JSON. @Serializable — chú thích. @SerialName — tên trường tùy chỉnh. Hỗ trợ: JSON, CBOR, ProtoBuf. Parcelize — @Parcelize cho Android Parcelable (không cần triển khai thủ công). Gson vs Moshi vs kotlinx: kotlinx.serialization — Kotlin-first, an toàn biên dịch, không reflection. Moshi — chú thích + codegen. IT Sectr khuyên dùng kotlinx.serialization cho dự án mới và Moshi cho dự án hiện có.

kotlin
@Serializable
data class ApiResponse<T>(
    val success: Boolean,
    @SerialName("data") val data: T? = null,
    val error: String? = null
)

@Serializable
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// Giải tuần tự hóa
val json = Json { ignoreUnknownKeys = true }
val response = json.decodeFromString<ApiResponse<List<User>>>(jsonString)
println("Users: ${response.data?.size ?: 0}")

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

Sự khác biệt giữa data class và sealed class là gì?

data class — cho dữ liệu (tự động tạo equals/hashCode/copy). sealed class — cho hệ thống phân cấp kiểu (kiểm tra trong when). sealed interface — tương tự với đa kế thừa.

Scope functions trong Kotlin là gì?

let, run, with, apply, also. Phân biệt bởi ngữ cảnh (it vs this) và giá trị trả về (result vs context). let — null safety, apply — cấu hình, also — tác dụng phụ.

CoroutineScope là gì và có những loại nào?

CoroutineScope — phạm vi coroutines. lifecycleScope — cho Activity, viewModelScope — cho ViewModel. GlobalScope — không khuyến nghị.

reified trong Kotlin là gì?

reified — bảo toàn kiểu trong hàm inline. Cho phép T::class và is T. Chỉ hoạt động với hàm inline.

Coroutine builders: launch, async, runBlocking là gì?

launch — không kết quả. async — có kết quả (Deferred). runBlocking — cầu nối chặn cho main/test. withContext — chuyển Dispatcher.

Tổng kết

  • data class — cho mô hình. sealed class — cho trạng thái. object — cho singleton.
  • Scope functions: let (null-safe), apply (cấu hình), run (tính toán), also (ghi log).
  • Coroutines: launch (fire-and-forget), async (có kết quả), withContext (chuyển Dispatcher).
  • viewModelScope — tiêu chuẩn cho ViewModel. lifecycleScope — cho Activity/Fragment.
  • reified — hàm inline an toàn kiểu. lateinit — DI, lazy — khởi tạo lười.
  • Extension functions — thêm chức năng không cần kế thừa.
  • Dispatchers: Main (UI), IO (mạng/đĩa), Default (CPU). Chọn đú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