Tin tức về sản phẩm

Có gì mới trong bản phát hành Jetpack Compose tháng 12 năm 2025

Đọc trong 6 phút
Nick Butcher
Giám đốc sản phẩm

Hôm nay, bản phát hành Jetpack Compose tháng 12 năm 2025 đã ổn định. Bản phát hành này chứa phiên bản 1.10 của các mô-đun Compose cốt lõi và phiên bản 1.4 của Material 3 (xem toàn bộ ánh xạ BoM (Bảng kê khai thành phần)), bổ sung các tính năng mới và cải thiện đáng kể hiệu suất.

Để sử dụng bản phát hành hôm nay, hãy nâng cấp phiên bản Compose BOM lên 2025.12.00:

implementation(platform("androidx.compose:compose-bom:2025.12.00"))

Cải thiện hiệu suất

Chúng tôi biết rằng hiệu suất khi bắt đầu chạy của ứng dụng là yếu tố vô cùng quan trọng đối với bạn và người dùng. Vì vậy, hiệu suất là ưu tiên hàng đầu của nhóm Compose. Bản phát hành này mang đến một số điểm cải tiến và bạn có thể sử dụng tất cả những điểm cải tiến này chỉ bằng cách nâng cấp lên phiên bản mới nhất. Các điểm chuẩn cuộn nội bộ của chúng tôi cho thấy Compose hiện có hiệu suất tương đương với khi bạn sử dụng Khung hiển thị:

janky.png

Điểm chuẩn hiệu suất cuộn so sánh giữa Khung hiển thị và Jetpack Compose trên nhiều phiên bản Compose

Thành phần có thể tạm dừng trong quá trình tìm nạp trước từng phần

Giờ đây, thành phần có thể tạm dừng trong quá trình tìm nạp trước theo cách linh hoạt được bật theo mặc định. Đây là một thay đổi cơ bản đối với cách hoạt động của thời gian chạy Compose, được thiết kế để giảm đáng kể hiện tượng giật trong quá trình tải giao diện người dùng nặng.

Trước đây, sau khi bắt đầu, một thành phần phải chạy cho đến khi hoàn tất. Nếu thành phần phức tạp, thì điều này có thể chặn luồng chính lâu hơn một khung hình, khiến giao diện người dùng bị treo. Với thành phần có thể tạm dừng, giờ đây, thời gian chạy có thể "tạm dừng" công việc nếu hết thời gian và tiếp tục công việc ở khung hình tiếp theo. Điều này đặc biệt hiệu quả khi được dùng với tính năng tìm nạp trước bố cục từng phần để chuẩn bị các khung hình trước thời gian. Các API CacheWindow bố cục Lazy được giới thiệu trong Compose 1.9 là một cách hiệu quả để tìm nạp trước nhiều nội dung hơn và hưởng lợi từ thành phần có thể tạm dừng để tạo ra hiệu suất giao diện người dùng mượt mà hơn nhiều.

pausable.gif

Thành phần có thể tạm dừng kết hợp với tính năng Tìm nạp trước từng phần giúp giảm hiện tượng giật

Chúng tôi cũng đã tối ưu hoá hiệu suất ở những nơi khác, với các điểm cải tiến đối với Modifier.onPlaced, Modifier.onVisibilityChanged và các phương thức triển khai đối tượng sửa đổi khác. Chúng tôi sẽ tiếp tục đầu tư để cải thiện hiệu suất của Compose.

Tính năng mới

Giữ lại

Compose cung cấp một số API để giữ và quản lý trạng thái trong các vòng đời khác nhau; ví dụ: remember duy trì trạng thái trong các thành phần và rememberSavable/rememberSerializable để duy trì trong quá trình tái tạo hoạt động hoặc quy trình. retain là một API mới nằm giữa các API này, cho phép bạn duy trì các giá trị qua các lần thay đổi cấu hình mà không cần được chuyển đổi tuần tự, nhưng không duy trì được khi bị buộc tắt. Vì retain không chuyển đổi tuần tự trạng thái của bạn, nên bạn có thể duy trì các đối tượng như biểu thức lambda, luồng và các đối tượng lớn như bitmap mà bạn không thể dễ dàng chuyển đổi tuần tự. Ví dụ: bạn có thể dùng retain để quản lý một trình phát nội dung nghe nhìn (chẳng hạn như ExoPlayer) nhằm đảm bảo quá trình phát nội dung nghe nhìn không bị gián đoạn do thay đổi cấu hình.

@Composable

fun MediaPlayer() {

    val applicationContext = LocalContext.current.applicationContext

    val exoPlayer = retain { ExoPlayer.Builder(applicationContext).apply { ... }.build() }

    ...

}

Chúng tôi xin gửi lời cảm ơn đến cộng đồng AndroidDev (đặc biệt là nhóm Circuit) vì đã ảnh hưởng và đóng góp vào việc thiết kế tính năng này.

Material 1.4

Thư viện material3 phiên bản 1.4.0 bổ sung một số thành phần và điểm cải tiến mới:

  • TextField hiện cung cấp phiên bản thử nghiệm dựa trên TextFieldState, cung cấp phương thức mạnh mẽ hơn để quản lý trạng thái của văn bản. Ngoài ra, hiện tại, chúng tôi cung cấp các biến thể SecureTextFieldOutlinedSecureTextField mới. Thành phần kết hợp Text hiện hỗ trợ hành vi autoSize.
  • Giờ đây, thành phần băng chuyền cung cấp một HorizontalCenteredHeroCarousel biến thể mới.
  • TimePicker hiện hỗ trợ việc chuyển đổi giữa bộ chọn và chế độ nhập.
  • Nút kéo dọc giúp người dùng thay đổi kích thước và/hoặc vị trí của ngăn thích ứng.
centered-hero-carousel.webp

Băng chuyền nổi bật nằm ngang ở giữa

Xin lưu ý rằng các API Material 3 Expressive sẽ tiếp tục được phát triển trong các bản phát hành alpha của thư viện material3. Để tìm hiểu thêm, hãy xem bài nói chuyện gần đây này:

Các tính năng mới về ảnh động

Chúng tôi tiếp tục mở rộng các API Ảnh động, bao gồm cả các bản cập nhật để tuỳ chỉnh ảnh động của thành phần dùng chung.

Các phần tử dùng chung linh hoạt

Theo mặc định, ảnh động sharedElement()sharedBounds() sẽ cố gắng tạo ảnh động

bố cục sẽ thay đổi bất cứ khi nào tìm thấy một khoá khớp trong trạng thái đích. Tuy nhiên, có thể bạn muốn tắt ảnh động này một cách linh động dựa trên một số điều kiện, chẳng hạn như hướng điều hướng hoặc trạng thái hiện tại của giao diện người dùng.

Để kiểm soát việc chuyển đổi phần tử dùng chung có diễn ra hay không, giờ đây, bạn có thể tuỳ chỉnh SharedContentConfig được truyền đến rememberSharedContentState(). Thuộc tính isEnabled xác định xem phần tử dùng chung có đang hoạt động hay không.

SharedTransitionLayout {

        val transition = updateTransition(currentState)

        transition.AnimatedContent { targetState ->

            // Create the configuration that depends on state changing.

            fun animationConfig() : SharedTransitionScope.SharedContentConfig {

                return object : SharedTransitionScope.SharedContentConfig {

                    override val SharedTransitionScope.SharedContentState.isEnabled: Boolean

                        get() =

                            // determine whether to perform a shared element transition

                }

            }

}

Hãy xem tài liệu để biết thêm thông tin.

Modifier.skipToLookaheadPosition()

Một đối tượng sửa đổi mới, Modifier.skipToLookaheadPosition(), đã được thêm vào bản phát hành này. Đối tượng sửa đổi này sẽ giữ vị trí cuối cùng của một composable khi thực hiện ảnh động thành phần dùng chung. Điều này cho phép thực hiện các hiệu ứng chuyển đổi như hoạt ảnh kiểu "hiện", như bạn có thể thấy trong mẫu Androidify với hiệu ứng hiện dần của camera. Hãy xem mẹo trong video tại đây để biết thêm thông tin: 

Vận tốc ban đầu trong hiệu ứng chuyển đổi phần tử dùng chung

Bản phát hành này bổ sung một API chuyển tiếp thành phần dùng chung mới, prepareTransitionWithInitialVelocity, cho phép bạn truyền vận tốc ban đầu (ví dụ: từ một cử chỉ) đến một lượt chuyển tiếp thành phần dùng chung:

Modifier.fillMaxSize()

    .draggable2D(

        rememberDraggable2DState { offset += it },

        onDragStopped = { velocity ->

            // Set up the initial velocity for the upcoming shared element

            // transition.

            sharedContentStateForDraggableCat

                ?.prepareTransitionWithInitialVelocity(velocity)

            showDetails = false

        },

    )
fling-shared.gif

Hiệu ứng chuyển đổi thành phần dùng chung bắt đầu với vận tốc ban đầu từ một cử chỉ

Chuyển cảnh có hiệu ứng che phủ

EnterTransition và ExitTransition xác định cách thành phần kết hợp AnimatedVisibility/AnimatedContent xuất hiện hoặc biến mất. Một lựa chọn mới mang tính thử nghiệm là lớp phủ cho phép bạn chỉ định màu để phủ hoặc che nội dung; ví dụ: làm mờ dần một lớp màu đen bán trong suốt trên nội dung:

veil_2.gif

Nội dung hoạt hình bị che phủ – lưu ý lớp che phủ (hoặc màn hình) bán trong suốt trên nội dung dạng lưới trong quá trình tạo ảnh động

AnimatedContent(

    targetState = page,

    modifier = Modifier.fillMaxSize().weight(1f),

    transitionSpec = {

        if (targetState > initialState) {

            (slideInHorizontally { it } togetherWith

                    slideOutHorizontally { -it / 2 } + veilOut(targetColor = veilColor))

        } else {

            slideInHorizontally { -it / 2 } +

                    unveilIn(initialColor = veilColor) togetherWith slideOutHorizontally { it }

        }

    },

) { targetPage ->

    ...

}

Những thay đổi sắp tới

Ngừng sử dụng Modifier.onFirstVisible

Compose 1.9 giới thiệu Modifier.onVisibilityChangedModifier.onFirstVisible. Sau khi xem xét ý kiến phản hồi của bạn, chúng tôi nhận thấy không thể xác định một cách chắc chắn thời điểm Modifier.onFirstVisible; cụ thể là khi một mục lần đầu tiên xuất hiện. Ví dụ: Bố cục Lazy có thể loại bỏ những mục cuộn ra khỏi khung hiển thị, rồi kết hợp lại những mục đó nếu chúng cuộn trở lại khung hiển thị. Trong trường hợp này, lệnh gọi lại onFirstVisible sẽ kích hoạt lại vì đây là một mục mới được tạo. Hành vi tương tự cũng sẽ xảy ra khi bạn điều hướng quay lại một màn hình đã truy cập trước đó có chứa onFirstVisible. Do đó, chúng tôi quyết định không dùng công cụ sửa đổi này trong bản phát hành Compose tiếp theo (1.11) và đề xuất bạn di chuyển sang onVisibilityChanged. Hãy xem tài liệu để biết thêm thông tin.

Điều phối coroutine trong các kiểm thử

Chúng tôi dự định thay đổi việc điều phối coroutine trong các bài kiểm thử để cải thiện độ ổn định của bài kiểm thử và phát hiện thêm nhiều vấn đề. Hiện tại, các thử nghiệm sử dụng UnconfinedTestDispatcher, khác với hành vi trong quá trình phát hành; ví dụ: hiệu ứng có thể chạy ngay lập tức thay vì được đưa vào hàng đợi. Trong một bản phát hành trong tương lai, chúng tôi dự định giới thiệu một API mới sử dụng StandardTestDispatcher theo mặc định để phù hợp với hành vi của bản phát hành công khai. Bạn có thể dùng thử hành vi mới ngay bây giờ trong phiên bản 1.10:

@get:Rule // also createAndroidComposeRule, createEmptyComposeRule

val rule = createComposeRule(effectContext = StandardTestDispatcher())

Việc sử dụng StandardTestDispatcher sẽ xếp hàng đợi các tác vụ, vì vậy, bạn phải sử dụng các cơ chế đồng bộ hoá như composeTestRule.waitForIdle() hoặc composeTestRule.runOnIdle(). Nếu kiểm thử của bạn sử dụng runTest, bạn phải đảm bảo rằng runTest và quy tắc Compose của bạn dùng chung một thực thể StandardTestDispatcher để đồng bộ hoá.

// 1. Create a SINGLE dispatcher instance

val testDispatcher = StandardTestDispatcher()



// 2. Pass it to your Compose rule

@get:Rule

val composeRule = createComposeRule(effectContext = testDispatcher)



@Test

// 3. Pass the *SAME INSTANCE* to runTest

fun myTest() = runTest(testDispatcher) {

    composeRule.setContent { /* ... */ }

}

Công cụ

Các API tuyệt vời xứng đáng có những công cụ tuyệt vời và Android Studio đã bổ sung một số tính năng gần đây cho nhà phát triển Compose:

Để xem cách các công cụ này hoạt động, hãy xem bản minh hoạ gần đây này:

Chúc bạn sáng tác vui vẻ

Chúng tôi tiếp tục đầu tư vào Jetpack Compose để cung cấp cho bạn các API và công cụ cần thiết để tạo giao diện người dùng đẹp mắt và phong phú. Chúng tôi rất trân trọng ý kiến đóng góp của bạn. Vì vậy, vui lòng chia sẻ ý kiến phản hồi về những thay đổi này hoặc những điều bạn muốn thấy tiếp theo trong trình theo dõi vấn đề của chúng tôi.

Tác giả:

Tiếp tục đọc