Jetpack Compose: nó là gì, khái niệm chính và hàm Composable

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

Jetpack Compose là một bộ công cụ khai báo hiện đại để xây dựng giao diện Android bằng Kotlin. Nhà phát triển mô tả UI thông qua các hàm composable và bộ công cụ tự động vẽ lại chỉ những phần đã thay đổi. Theo Android Developers (2026), Jetpack Compose chạy trên Android 5.0 (API 21) trở lên, hỗ trợ Material Design 3 và đạt 120 FPS trên các thiết bị tầm trung nhờ hệ thống Recomposition riêng — một thuật toán diff thông minh chỉ cập nhật các widget đã thay đổi.

Những điểm chính

  • Jetpack Compose — một framework UI khai báo cho Android, nơi giao diện được xây dựng thông qua các hàm @Composable trong Kotlin.
  • Recomposition — cơ chế tự động cập nhật chỉ những thành phần có dữ liệu thay đổi, đạt 120 FPS.
  • State được quản lý qua mutableStateOf, collectAsState và StateFlow — khi giá trị thay đổi, composition khởi động lại cho các view phụ thuộc.
  • Modifier — một chuỗi các hàm để cấu hình đệm, kích thước, nền, nhấp chuột và hoạt ảnh mà không cần kế thừa lớp.
  • Side Effects — LaunchedEffect, DisposableEffect và rememberCoroutineScope — quản lý các hành động phụ: bộ đếm thời gian, yêu cầu mạng, đăng ký.

Jetpack Compose là gì?

Jetpack Compose là một framework khai báo của Google để xây dựng giao diện người dùng Android, được công bố vào năm 2019 và đạt bản phát hành ổn định vào năm 2021. Không giống như View System cũ (bố cục XML + Activity/Fragment), Compose sử dụng các hàm Kotlin được chú thích — @Composable. Giao diện được mô tả hoàn toàn bằng Kotlin: không có sự phân chia giữa XML và mã. Điều này đã loại bỏ lớp lỗi liên quan đến ID không khớp trong XML và Kotlin (type-safe synthetic không giúp ích khi tái cấu trúc).

Compose được xây dựng trên hệ thống kết xuất riêng — Canvas, không gắn với hệ phân cấp View. Mỗi Composable tự vẽ trực tiếp lên Canvas, bỏ qua onMeasure/onDraw của View System. Điều này mang lại hiệu suất vượt trội trên các màn hình phức tạp: trong các thử nghiệm của Google (2023), màn hình Compose với 200 phần tử kết xuất nhanh hơn 40% so với màn hình tương tự trên RecyclerView + ViewHolder.

Yêu cầu tối thiểu và tương thích

Compose yêu cầu minSdk 21 (Android 5.0) và Kotlin 1.9+. BOM (Bill of Materials) của Compose đồng bộ hóa phiên bản của tất cả các thư viện Compose. Framework tương thích với mã View System hiện có: Compose được nhúng qua ComposeView trong bố cục XML và các View cũ qua AndroidView trong hệ phân cấp Compose. Theo Google Play Console (2025), Android 5.0+ bao phủ 97% thiết bị đang hoạt động, do đó tính tương thích không phải là hạn chế đối với hầu hết các dự án.

Hàm Composable và composition

@Composable là một chú thích biến một hàm Kotlin thông thường thành một khối xây dựng UI. Hàm Composable mô tả một phần giao diện sẽ trông như thế nào — văn bản, nút bấm, danh sách. Thay vì trả về một giá trị, hàm phát ra (emit) các thành phần UI vào composition. Điều này giống như một trình tạo: mỗi hàm thêm các phần tử vào màn hình khi được gọi.

kotlin
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
    Card(
        modifier = Modifier.fillMaxWidth().padding(16.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surface
        )
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            AsyncImage(
                model = avatarUrl,
                contentDescription = "Ảnh đại diện",
                modifier = Modifier.size(48.dp).clip(CircleShape)
            )
            Spacer(Modifier.width(12.dp))
            Text(
                text = name,
                style = MaterialTheme.typography.titleMedium
            )
        }
    }
}

Hàm ProfileCard nhận tham số (name, avatarUrl) và phát ra Card → Row → AsyncImage + Text. Composition là cây các thành phần được phát ra trong một lần. Nếu các tham số không thay đổi, Compose bỏ qua lời gọi hàm (recomposition skip). Nếu chỉ name thay đổi, chỉ Text được gọi, các phần tử còn lại không được vẽ lại. Sự tái composition thông minh này là lợi thế hiệu suất chính của Compose so với tối ưu hóa thủ công của View System.

Slot và Content Lambda

Các hàm Composable tích cực sử dụng slot — trailing lambda, content: @Composable (() -> Unit). Điều này cho phép tạo các vùng chứa: Card, Column, Row chấp nhận lambda content và nội dung được nhúng vào slot. Slot API đã thay thế các thuộc tính XML như android:layout_gravity — giờ đây vị trí của các phần tử con được đặt bằng mã Kotlin bên trong khối nội dung.

Quản lý trạng thái trong Compose

State trong Compose là bất kỳ giá trị nào có thể thay đổi theo thời gian. Khi trạng thái thay đổi, Compose lên lịch tái composition cho tất cả các thành phần đọc trạng thái này. Cơ chế này tương tự như React hooks: mutableStateOf trả về MutableState<T>, việc đọc .value tự động đăng ký composition hiện tại theo dõi các thay đổi.

kotlin
@Composable
fun CounterExample() {
    var count by remember { mutableStateOf(0) }

    Column(modifier = Modifier.padding(16.dp)) {
        Text("Đã nhấp: $count")
        Button(onClick = { count++ }) {
            Text("Tăng")
        }
    }
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val userName by viewModel.userName.collectAsState()
    Text("Người dùng: $userName")
}

remember giữ giá trị giữa các lần tái composition — nếu không thì mutableStateOf sẽ được tạo lại mỗi khi UI được cập nhật. collectAsState() chuyển đổi StateFlow từ ViewModel thành trạng thái tương thích với Compose. Khuyến nghị — sử dụng ViewModel với StateFlow cho trạng thái cấp màn hình và mutableStateOf cho trạng thái cục bộ (ví dụ: thẻ mở rộng). Sự phân tách này tuân theo nguyên tắc thành phần thông minh/đơn giản.

State Hoisting

State Hoisting là mẫu nâng trạng thái từ thành phần con lên thành phần cha. Cha truyền giá trị và callback qua tham số, con gọi callback khi thay đổi. Cha giữ mutableStateOf, con chỉ giữ tham số. Điều này làm cho thành phần có thể tái sử dụng và kiểm thử được: cùng một TextField có thể được sử dụng với bất kỳ nguồn dữ liệu nào.

Modifier — tùy chỉnh giao diện

Modifier là một đối tượng mô tả các biến đổi của Composable: kích thước, đệm, nền, xử lý nhấp chuột, hoạt ảnh, cuộn. Các modifier được áp dụng qua chuỗi gọi: Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }. Mỗi lần gọi trả về một Modifier mới với thuộc tính được thêm vào — không làm thay đổi đối tượng gốc.

Thứ tự của các modifier rất quan trọng. Modifier.padding(16.dp).background(Color.Blue) tô màu vùng có đệm. Modifier.background(Color.Blue).padding(16.dp) tô màu hình chữ nhật bên trong và phần đệm vẫn trong suốt. Cơ chế tương tự như mô hình hộp CSS: padding trước → background hoạt động như margin + background; background trước → padding hoạt động như background + đệm bên trong. Nhà phát triển chỉ cần nhớ: padding trước = lề ngoài, padding sau = đệm trong.

Modifier tùy chỉnh

Nếu các modifier tích hợp không đủ, có thể tạo modifier tùy chỉnh qua Modifier.composed { ... } hoặc Modifier.then(). Bên trong modifier tùy chỉnh, có thể sử dụng đo lường bố cục (Modifier.layout { measurable, constraints -> ... }), vẽ (Modifier.drawWithContent { ... }), cử chỉ (Modifier.pointerInput { ... }). Ví dụ: modifier cho hoạt ảnh nhấp nháy khi nhấp chuột — đo kích thước, khi nhấp chuột bắt đầu hoạt ảnh tỷ lệ qua animateFloatAsState.

Đối với hoạt ảnh, Compose cung cấp animate*AsState (animateFloatAsState, animateColorAsState, animateDpAsState) — các giá trị hoạt ảnh giữa trạng thái cũ và mới khi thay đổi. Đối với hoạt ảnh xuất hiện/biến mất — AnimatedVisibilityAnimatedContent với các chuyển tiếp tích hợp (fade, slide, expand). Tất cả hoạt ảnh hoạt động trên lớp đồ họa mà không kích hoạt composition không cần thiết.

Side Effects: LaunchedEffect, DisposableEffect, remember

Các hàm Composable không nên thực hiện tác dụng phụ trực tiếp (yêu cầu mạng, bộ đếm thời gian, đăng ký) — chúng được gọi ở mỗi lần tái composition, dẫn đến các yêu cầu trùng lặp. Đối với tác dụng phụ, Compose cung cấp một họ các hàm Effect: LaunchedEffect bắt đầu một coroutine khi vào composition và hủy nó khi thoát, DisposableEffect — cho các tài nguyên cần dọn dẹp rõ ràng (cảm biến, BroadcastReceiver).

kotlin
@Composable
fun SensorReader() {
    val context = LocalContext.current
    var sensorValue by remember { mutableStateOf(0f) }

    DisposableEffect(Unit) {
        val sensor = registerSensorListener(context) { value ->
            sensorValue = value
        }
        onDispose {
            unregisterSensorListener(sensor)
        }
    }

    Text("Giá trị: $sensorValue")
}

@Composable
fun UserGreeting(userId: String) {
    LaunchedEffect(userId) {
        val profile = api.fetchProfile(userId)
        // cập nhật trạng thái
    }
}

LaunchedEffect(userId) khởi động lại nếu userId thay đổi — coroutine trước đó bị hủy, một coroutine mới bắt đầu với userId mới. Điều này loại bỏ việc quản lý hủy yêu cầu thủ công. DisposableEffect(Unit) — một hiệu ứng với khóa cố định Unit, kích hoạt khi vào composition và gọi onDispose khi thoát. SensorReader đăng ký một trình lắng nghe và hủy đăng ký khi rời khỏi màn hình — không có rủi ro rò rỉ.

rememberCoroutineScope

Nếu cần bắt đầu một coroutine không phải khi vào composition mà khi có sự kiện (nhấp nút), hãy sử dụng rememberCoroutineScope(). Nó trả về một CoroutineScope gắn với vòng đời của Composable, không yêu cầu DisposableEffect. Ví dụ: bắt đầu yêu cầu mạng khi nhấp nút — scope.launch { viewModel.loadData() }.

Jetpack Compose vs View System: so sánh

Lựa chọn giữa Compose và View System là câu hỏi kiến trúc chính cho các nhà phát triển Android vào năm 2026. Cả hai công nghệ đều được Google hỗ trợ, nhưng Compose là hướng chính mà Google đầu tư nguồn lực. View System chỉ nhận được các bản sửa lỗi quan trọng và không phát triển. Sự khác biệt thể hiện ở cú pháp, quản lý trạng thái, hiệu suất và thời gian phát triển.

Khía cạnhJetpack ComposeView System
Mô tả UIHàm Kotlin @ComposableBố cục XML + Activity/Fragment
Trạng tháimutableStateOf, StateFlow, tự động vẽ lạifindViewById, thủ công: setText, notifyDataSetChanged
Hiệu suấtTái composition thông minh, kết xuất CanvasHệ phân cấp View, measure/layout/draw
Hoạt ảnhanimate*AsState, AnimatedVisibility, tích hợpValueAnimator, ObjectAnimator, Transition
Tương thíchminSdk 21, cầu nối ComposeView/AndroidViewTất cả phiên bản, bất kỳ
Kích thước APK+3–5 MB cho ComposeKhông có chi phí

Đối với các dự án mới, Google khuyến nghị Jetpack Compose làm tiêu chuẩn phát triển UI. View System vẫn được duy trì để bảo trì mã viết trước năm 2021 và cho các trường hợp kích thước APK tối thiểu là quan trọng (ví dụ: thị trường mới nổi với thiết bị cấp thấp). Compose giảm khối lượng mã UI từ 30–50% so với View System nhờ cú pháp khai báo và hoạt ảnh tích hợp.

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

Tôi có thể sử dụng Compose trong dự án View System hiện có không?

Có, thông qua ComposeView trong bố cục XML. Thêm dependency Compose và bọc màn hình hoặc một phần của nó trong ComposeView { MyComposable() }. Việc di chuyển thực hiện từng màn hình.

Tại sao Composable của tôi vẽ lại quá thường xuyên?

Nguyên nhân là trạng thái được nâng lên quá cao hoặc các đối tượng có thể thay đổi được sử dụng. Khắc phục: derivedStateOf cho dữ liệu dẫn xuất và remember cho các tham chiếu ổn định.

Làm thế nào để triển khai danh sách trong Compose?

Sử dụng LazyColumn (tương tự RecyclerView). Các phần tử được tạo và tái sử dụng khi cuộn. Đối với danh sách phức tạp với nhiều loại ô — LazyColumn { items(items, key = { it.id }) { ... } }.

Tôi có cần học View System trước Compose không?

Không, bạn có thể bắt đầu trực tiếp với Compose. Kiến thức về View System giúp ích khi bảo trì mã kế thừa, nhưng Compose là một hệ sinh thái độc lập với tài liệu và mẫu thiết kế riêng.

Compose có hỗ trợ Material 3 không?

Có, Material 3 là chủ đề tiêu chuẩn của Compose từ năm 2023. Nó được thêm qua implementation("androidx.compose.material3:material3"). Material 2 được coi là không còn được khuyến khích.

Tóm tắt

  • Jetpack Compose — một framework UI khai báo cho Android, nơi toàn bộ giao diện được viết bằng Kotlin qua các hàm @Composable.
  • Recomposition tự động vẽ lại chỉ các thành phần đã thay đổi, đạt 120 FPS mà không cần tối ưu thủ công.
  • State được quản lý qua mutableStateOf, collectAsState và StateFlow; mẫu State Hoisting làm cho các thành phần có thể tái sử dụng.
  • Modifier — một chuỗi các biến đổi để cấu hình giao diện, hoạt ảnh và hành vi mà không cần kế thừa lớp.
  • Side Effects (LaunchedEffect, DisposableEffect) cách ly các hành động phụ khỏi tái composition, ngăn rò rỉ và yêu cầu trùng lặp.
  • LazyColumn thay thế RecyclerView với ít mã hơn và AnimatedVisibility thay thế các chuỗi Animator phức tạp.
  • Google khuyến nghị Compose cho tất cả các dự án mới; View System vẫn được duy trì cho mã kế thừa và các trường hợp kích thước APK tối thiểu là quan trọ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