Nền tảng ứng dụng

Di chuyển ứng dụng Google Play có tuổi đời hai thập kỷ sang Jetpack Compose

Loa

  • Kirill Grouchnikov

    Kỹ sư phần mềm

  • Jon Boekenoogen

    Kỹ sư phần mềm

Giới thiệu

Giới thiệu về bài thuyết trình

Năm nay, Android chính thức ưu tiên Compose để xây dựng mọi giao diện người dùng, đồng thời chuyển các Khung hiển thị cũ sang chế độ bảo trì. Đối với Google Play, hành trình đó bắt đầu từ năm 2020. Trong suốt gần hai thập kỷ phát triển kỹ thuật và phục vụ hàng tỷ người dùng, quá trình di chuyển sang Jetpack Compose đã thành công nhờ áp dụng các phương pháp hay nhất đã được chứng minh, sự hợp tác chặt chẽ với nhóm Compose chính và sự phát triển không ngừng của các công cụ.

Khám phá cách hiện đại hoá Google Play bằng Compose giúp cải thiện đáng kể tốc độ và độ ổn định lâu dài. Phiên này sẽ hướng dẫn cách kết nối quy trình thiết kế Figma dựa trên tác nhân với quá trình triển khai Compose, tự động hoá chất lượng để ngăn chặn việc kết hợp lại không cần thiết và tạo giao diện biểu cảm bằng màu sắc động, kiểu chữ phong phú và hình dạng phân lớp. Bạn sẽ nắm được các chiến lược đã được kiểm chứng để phân loại lỗi nhanh hơn và tự tin mở rộng quy mô di chuyển sang Compose.

Tóm tắt

  • Google Play đã chuyển 97% số lượt hiển thị của người dùng sang màn hình chỉ dùng Compose trong hơn 6 năm. Các trang chính cũng ghi nhận tỷ lệ giật giảm 30% trong 14 tháng qua.
  • Việc áp dụng dần dần giúp giảm thiểu rủi ro kinh doanh trên các cơ sở mã lớn. Các nhóm có thể làm quen với màn hình có lưu lượng truy cập thấp trước, sau đó tiến tới lưu trữ ComposeView ngay tại gốc Hoạt động.
  • Giao diện động hoạt động hoàn toàn trong mã bằng cách sử dụng lớp phủ MaterialTheme và thư viện Tiện ích màu Material. Điều này giúp tránh việc huỷ bỏ Hoạt động, mặc dù việc tạo bảng phối màu tại thời điểm xây dựng giúp hạn chế độ trễ trong thời gian chạy.
  • Luồng dữ liệu một chiều và giao diện người dùng khai báo giúp đơn giản hoá cấu trúc và loại bỏ một số loại tình huống tương tranh. Việc chạy song song các nguồn dữ liệu và phép biến đổi giao diện người dùng đã cải thiện độ trễ tải của Google Play thêm hàng chục mili giây.
  • Tính năng kiểm tra Lint tự động thực thi các quy tắc về chất lượng mã và hệ thống thiết kế. Play sử dụng các quy tắc này để chặn màu được mã hoá cứng và gắn cờ các lỗi tiềm ẩn về hiệu suất, chẳng hạn như BoxWithConstraints.

Gemini Notebook

Chủ đề

  • jetpack-compose
  • di chuyển
  • hiệu suất
  • sắp xếp theo chủ đề
  • unidirectional-data-flow
  • lint-rules
  • developer-velocity

Bản chép lời

Giới thiệu và mức độ sử dụng Cửa hàng Google Play

  • Chào mừng các bạn!

  • Tôi là Jon.

  • Tôi là thành viên của nhóm Cửa hàng Google Play.

  • Đây là đồng nghiệp của tôi, Kirill.

  • Hôm nay, chúng tôi sẽ chia sẻ về cách chúng tôi chuyển nhiều mã từ hệ thống Chế độ xem và Fragment sang Compose.

  • Hãy bắt đầu nào.

  • Vậy quá trình áp dụng diễn ra như thế nào và quy mô ra sao?

  • Vì vậy, đối với toàn bộ mã nguồn ứng dụng của chúng tôi, nó thực sự phát triển một cách tự nhiên kể từ khoảng năm 2007.

  • Chúng tôi có vài triệu dòng mã phát hành chính thức, 200 màn hình và 500 thành phần giao diện người dùng riêng biệt được dùng trên nhiều màn hình trong số đó.

  • Vào năm 2020, chúng tôi nhận thấy tốc độ, độ tin cậy và hiệu suất của nhà phát triển bắt đầu không đạt được mục tiêu mà chúng tôi mong muốn.

  • Vì vậy, chúng tôi quyết định áp dụng một bộ phần mềm cơ sở hiện đại cho giao diện người dùng.

  • Chúng tôi đã đánh giá một loạt thư viện khác nhau.

  • Chúng tôi cũng có một số người bạn trong AndroidX nói chuyện với chúng tôi về Compose vào thời điểm đó, và chúng tôi quyết định áp dụng Compose và trở thành đối tác lớn đầu tiên của Compose.

  • Thế nào rồi?

  • Sáu năm sau, chúng tôi hiện có 97% lượt hiển thị của người dùng trong ứng dụng Cửa hàng Play trên các màn hình chỉ dùng Compose.

  • Tất cả, xin lỗi, tất cả hoạt động phát triển cho điện thoại và màn hình lớn đều đã chuyển sang chỉ dùng Compose kể từ năm 2020.

  • Và ngay cả các hệ số hình dạng mở rộng của chúng tôi như XR, TV, Auto, Wear cũng đã chuyển sang Compose kể từ năm 2025.

  • Compose là một yếu tố quan trọng giúp chúng tôi đạt được thành công đó và là lý do chúng tôi tiếp tục áp dụng Compose nhiều hơn.

  • Họ có một bộ kiểm thử rất mạnh mẽ và toàn diện, giúp chúng tôi áp dụng các phiên bản mới của Compose hai lần một tuần.

  • Việc sử dụng các bản dựng alpha và API mới giúp chúng tôi tận dụng các bản sửa lỗi mới, cải thiện hiệu suất mới và thực sự khám phá một số API mới đó, đồng thời mang đến trải nghiệm người dùng mới.

  • Nói riêng về hiệu suất, Compose thực sự đã mang lại hiệu suất ổn định cho ứng dụng của chúng tôi trên tất cả các màn hình chính.

  • Đây là trang kết quả tìm kiếm, trang chủ, trang thông tin chi tiết.

  • Đây là những chỉ số rất quan trọng, hiệu suất, độ giật và độ trễ tải, đối với hoạt động kinh doanh của chúng tôi cũng như trải nghiệm người dùng.

  • Vì vậy, chúng tôi đã thấy mức cải thiện 30% trong 14 tháng qua.

Kế hoạch di chuyển

  • Nhưng thành tựu này được vun đắp như thế nào?

  • Đó chính là điều chúng ta sẽ thảo luận hôm nay.

  • Hãy cùng tìm hiểu về kế hoạch di chuyển.

  • Vì vậy, Play đã áp dụng một phương pháp gồm nhiều bước.

  • Chúng tôi không muốn dồn hết trứng vào một giỏ.

  • Chúng tôi đã thực hiện một vài bước để tìm hiểu rủi ro, mức độ ảnh hưởng của rủi ro đối với hoạt động kinh doanh của chúng tôi và thực sự xây dựng niềm tin trước khi dốc toàn lực.

  • Vì vậy, tôi sẽ đặt tên cho các giai đoạn đó là: bò, đi, chạy bộ và chạy.

  • Vì vậy, việc thu thập thông tin đối với chúng tôi thực sự là để làm quen với Compose.

  • Chúng tôi bắt đầu với một trang có lưu lượng truy cập thấp.

  • Đây có thể là trang cài đặt, giấy phép của bên thứ ba, v.v.

  • Mục tiêu chính của bạn là làm quen với thư viện Compose.

  • Vì vậy, bạn có thể làm quen với Hàng, Cột, Văn bản, hình ảnh và tất cả những thành phần tương tự.

  • Sau đó, bạn cần bắt đầu đưa tất cả cơ sở hạ tầng ứng dụng vào và tìm hiểu cách hoạt động của cơ sở hạ tầng đó theo cách của Compose.

  • Vì vậy, đây có thể là ghi nhật ký lượt hiển thị, ghi nhật ký lượt nhấp, giao diện, chúng tôi đang cải tiến việc tải dữ liệu cùng một lúc.

  • Vậy nên, tất cả những điều này đều quan trọng.

  • Và một điều cụ thể mà chúng tôi thấy hữu ích là để đảm bảo rằng tất cả màn hình đều nhất quán, chúng tôi đã xây dựng một số kiểm thử đơn vị và kiểm tra về mặt hoạt động để kiểm tra xem các đối tượng giao diện trong Compose có liên kết trực tiếp với kiểu XML, kiểu chữ, màu sắc, tất cả những thứ này hay không.

  • Vì vậy, sau khi đã quen và cảm thấy thoải mái, chúng tôi quyết định chuyển sang đi bộ.

  • Đối với chúng tôi, việc này là lấy một thành phần nhỏ hơn trên màn hình có lưu lượng truy cập rất cao và đánh giá xem quá trình di chuyển đó sẽ như thế nào.

  • Bạn nên lấy một mục trong RecyclerView để có thể hiểu mọi vấn đề về khả năng tương thích giữa Khung hiển thị và hệ thống Compose, đồng thời xem hiệu suất đo lường và hiện tượng giật trong suốt quá trình.

  • Bản thân thành phần không cần phải quá phức tạp, nhưng bạn thực sự muốn có một thành phần thực hiện bố cục, và bạn biết đấy, Văn bản, hình ảnh, những thứ tương tự, một vài phiên bản khác nhau của những gì bạn thường thấy.

  • Một điều mà bạn nên chú ý và có thể dự kiến trong lĩnh vực này là hiện tượng giật và độ trễ tăng lên một chút, nhưng điều này là do bạn hiện đang chạy hai ngăn xếp.

  • Bạn có một ngăn xếp kết xuất hoàn toàn trong Compose và một ngăn xếp trong Khung hiển thị.

  • Vì vậy, sẽ có một số hiện tượng dồn dập bộ nhớ, một số lượt tải lớp bổ sung, tất cả những điều này.

  • Nhưng khi bạn áp dụng Compose ngày càng nhiều, thì điều đó sẽ biến mất.

  • Nếu thực sự cần trong thời gian chờ đợi, bạn có thể làm nóng trước một chút màn hình đó để giúp màn hình hoạt động ổn định và giảm thiểu chi phí đó trong thời gian ngắn.

  • Sau khi đi bộ, chúng ta chuyển sang chạy bộ.

  • Vì vậy, đây là khi chúng ta đã rất, rất thoải mái.

  • Thay vì chỉ triển khai một thành phần trên trang có lưu lượng truy cập cao, hãy triển khai toàn bộ trang có lưu lượng truy cập cao.

  • Vì vậy, chúng tôi vẫn giữ thư viện điều hướng và sử dụng Mảnh, nhưng đối với mỗi màn hình riêng lẻ, màn hình đó được triển khai hoàn toàn trong Compose.

  • Chúng ta chỉ cần để Fragment trả về chính ComposeView.

  • Vì vậy, bạn có thể mong đợi độ trễ và hiện tượng giật hình được cải thiện.

  • Bạn sẽ không gặp phải tình trạng dồn dập bộ nhớ và tải lớp như tôi đã nói.

  • Bản thân Compose cũng thực hiện một số cấp độ lưu vào bộ nhớ đệm ở cấp ComposeView.

  • Vì vậy, nếu bạn có một RecyclerView với một loạt thẻ trông nhất quán và có thể có cùng biểu tượng, thì tất cả việc phân tích cú pháp biểu tượng và mức sử dụng tài nguyên đó sẽ được chia sẻ cho mọi thành phần trong ComposeView.

  • Sau đó, chúng tôi chuyển sang chạy bộ.

  • Đây là lúc bạn thực sự dốc toàn lực.

  • Sau khi bạn có phần lớn lưu lượng truy cập từ ứng dụng trên Compose, chúng ta sẽ chuyển lên một cấp.

  • Vì vậy, phía trên màn hình, chúng ta có Activity.

  • Vì vậy, hãy di chuyển ComposeView sang gốc Hoạt động.

  • Và nhiều đoạn mã của bạn sẽ trông tương đối giống nhau.

  • Bạn vẫn đang cố gắng thực hiện một lệnh điều hướng mà bạn muốn nói, di chuyển từ màn hình này sang màn hình khác.

  • Nhưng thay vì thực hiện các giao dịch Fragment, bạn sẽ gọi một hàm composable.

  • Bạn có thể thực hiện việc này trên thư viện Nav2 hoặc thư viện Nav3, tuỳ bạn chọn.

  • Đối với chúng tôi, chúng tôi chưa di chuyển tất cả màn hình.

  • Tôi đã nói là chúng tôi có rất nhiều mà.

  • Vì vậy, chúng tôi đã xây dựng khả năng tương thích với Fragment, trong đó bạn có thể có màn hình dựa trên Fragment và tận dụng trình bao bọc AndroidFragment của Compose để thực hiện việc này.

  • Điều bạn có thể mong đợi là hiện tượng giật và độ trễ rất quan trọng đối với hoạt động kinh doanh của chúng tôi, vì vậy, chúng tôi luôn nỗ lực cải thiện vấn đề này và bạn sẽ thấy vấn đề này được cải thiện vì hiện tại chúng tôi đã có bộ nhớ đệm trên các màn hình và giảm thiểu đáng kể vấn đề về việc dọn dẹp bộ nhớ.

  • Nhưng bạn cũng có thêm các tính năng mới.

  • Chúng tôi có một ví dụ về hiệu ứng này ở bên phải trong ảnh GIF này, nơi bạn có thể thực hiện hiệu ứng chuyển đổi phần tử dùng chung giữa các màn hình.

  • Vì vậy, chúng ta có một hình ảnh được phóng to khi bạn di chuyển từ màn hình này sang màn hình khác và hình ảnh đó mang lại sự liên tục.

  • Bạn cũng có thể tận dụng tất cả tính linh hoạt của ảnh động trong Compose trong khi thực hiện toàn bộ quá trình chuyển đổi đó.

  • Sau đây, tôi xin nhường lời cho Kirill để chia sẻ thêm về một số tính năng khác.

Giao diện và hiệu suất

  • Cảm ơn Jon.

  • Tôi muốn nói một chút về một chủ đề mà tôi rất tâm huyết, đó là giao diện và kiểu cho ứng dụng Android, một việc mà tôi đã làm trong một thời gian.

  • Trong thế giới Khung hiển thị, có mã Java và sau đó một chút là mã Kotlin, rồi đến tài nguyên X-- XML, các tài nguyên như màu sắc, chuỗi, kích thước, bố cục, giao diện và kiểu.

  • Và cách hoạt động là tất cả các tài nguyên XML này được biên dịch thành một bảng tài nguyên có trong APK và hầu như là tĩnh.

  • Có một API Resources.Theme.applyStyle mà bạn có thể sử dụng linh hoạt trong thời gian chạy để áp dụng kiểu tuỳ chỉnh lên trên hệ phân cấp giao diện người dùng.

  • Hạn chế lớn nhất là bạn phải thực hiện việc này trước khi tăng cường nội dung. Điều này có nghĩa là nếu muốn áp dụng linh động kiểu đó cho một thành phần giao diện người dùng hiện có, bạn phải huỷ bỏ và tạo lại toàn bộ Hoạt động. Điều này không tốt cho trải nghiệm người dùng.

  • Ngoài ra, vì áp dụng các khối XML được biên dịch trước này, nên việc kết hợp nhiều lớp phủ động có điều kiện với nhau dựa trên cờ thử nghiệm hoặc bất kỳ nhu cầu kinh doanh nào khác trở nên khó khăn.

  • Thật khó để xây dựng một mô hình tư duy phù hợp về hệ phân cấp kiểu trong thế giới XML đó.

  • Và cuối cùng, không có một chế độ xem thống nhất nào trong Android Studio hoặc bất kỳ công cụ cho nhà phát triển nào khác cho phép bạn thu hẹp khoảng cách giữa thế giới Java, thế giới mã và thế giới XML.

  • Và việc này khá khó khăn để xử lý và xây dựng mô hình tinh thần phù hợp, cũng như gỡ lỗi lý do kiểu của tôi không được áp dụng, lý do tôi nhận được màu không chính xác, v.v.

  • Trong thế giới mới, thế giới của Compose, cụ thể là hệ thống Material Design và thư viện Compose Material, cũng như các hệ thống thiết kế khác, chúng ta có một MaterialTheme Composable cho hệ thống Material Design. Bạn có thể áp dụng thành phần này cho phần trên cùng của hệ phân cấp giao diện người dùng trên màn hình, đồng thời cũng có thể áp dụng MaterialTheme này làm lớp phủ trên bất kỳ phần nhỏ nào của giao diện người dùng.

  • Nếu nhìn vào màn hình bên phải, bạn có thể thấy thẻ Play Points Gold ở trên cùng, đây là một thẻ nhỏ có chỉ báo tiến trình và một vài dòng văn bản.

  • Chúng tôi áp dụng lớp phủ Giao diện Material này bằng bảng phối màu tuỳ chỉnh do thư viện Tiện ích màu Material tạo ra, có sẵn trên GitHub để bạn sử dụng.

  • Chúng ta truyền vào một màu hạt giống, chẳng hạn như màu vàng nâu, vàng kim này, và màu này sẽ tạo ra toàn bộ dải mã thông báo màu Material, màu chính trên màu chính, màu phụ trên màu phụ, sau đó chúng ta sẽ sử dụng trong quá trình triển khai thẻ này.

  • Và điều này mang lại toàn bộ khả năng tạo giao diện động cho các nhà phát triển Android.

  • Tất cả đều được thực hiện bằng mã, tất cả đều được thực hiện bằng Kotlin, nghĩa là việc xây dựng mô hình tư duy phù hợp về cách mọi thứ hoạt động sẽ dễ dàng hơn nhiều và việc gỡ lỗi cũng dễ dàng hơn nhiều.

  • Và trong nội bộ, các lớp phủ này được đính kèm dưới dạng thành phần kết hợp cục bộ vào các nút giao diện người dùng cụ thể trong hệ phân cấp mà bạn chọn áp dụng.

  • Những điều cần lưu ý về hiệu suất: việc tạo bảng phối màu đầy đủ bằng thư viện Material Color Utilities không phải là miễn phí.

  • Điều này cũng đi kèm với một số chi phí nhất định.

  • Vì vậy, nếu bạn có một thứ gì đó đủ phức tạp cần nhiều bảng phối màu, chẳng hạn như một loại hộp bento hoặc bất cứ thứ gì, tuỳ thuộc vào nhu cầu của sản phẩm và bạn có nhiều bảng phối màu mà bạn tạo trong thời gian chạy, thì điều đó sẽ bắt đầu tăng lên, bắt đầu làm tăng độ trễ và hiện tượng giật.

  • Vì vậy, bạn nên bắt đầu đo lường mức độ ảnh hưởng của việc này đến hiệu suất và giảm bớt một số hao tổn này từ thời gian chạy sang thời gian xây dựng.

  • Bạn có thể sử dụng cùng một thư viện Material Color Utilities tại thời điểm xây dựng để tạo trước các bảng phối màu đó dựa trên nhu cầu xây dựng thương hiệu hoặc nhu cầu về sản phẩm, đồng thời giảm bớt hao tổn này cho thời gian xây dựng.

  • Đối với những thành phần cục bộ mà tôi đã đề cập để theo dõi chính xác vị trí của lớp phủ trong cây phân cấp giao diện người dùng, những thành phần đó có chi phí thấp hơn nhiều nhưng vẫn không miễn phí.

  • Vì vậy, tuỳ thuộc vào số lượng bạn sử dụng, hàng chục, hàng trăm, chi phí sẽ bắt đầu tăng lên.

  • Và tại một thời điểm nào đó, bạn muốn bắt đầu xem xét chi phí của tất cả các thành phần cục bộ kết hợp này.

  • Và đây là một ví dụ về những gì tôi đã đề cập, giống như khả năng tạo giao diện linh động thực sự trong thời gian chạy của Compose.

  • Ở đây, chúng ta có 4 góc phần tư, cùng một hình ảnh, cùng một thẻ sự kiện.

  • Chúng ta có hình ảnh chính này trải dài trên toàn bộ thẻ, sau đó chúng ta có một nhãn ở trên cùng bên trái, một nút ở dưới cùng bên phải và một vài văn bản.

  • Và ở bên phải của mỗi góc phần tư, bạn sẽ thấy chú thích về mã thông báo màu được dùng làm thông số thiết kế cho từng phần tử.

  • Cách triển khai thẻ là như nhau cho cả bốn thẻ này.

  • Điểm khác biệt duy nhất là lớp phủ Tuỳ chỉnh giao diện Material bao bọc thẻ được tạo hoặc định cấu hình bằng bảng phối màu được tạo linh động dựa trên màu chủ đạo của hình ảnh: xanh dương, tím, vàng và đỏ.

  • Mọi thứ khác vẫn giữ nguyên.

  • Bạn không cần phải huỷ và tạo lại hoạt động.

  • Bạn có thể áp dụng có điều kiện dựa trên cờ thử nghiệm hoặc bất kỳ nhu cầu kinh doanh nào khác.

  • Và như tôi đã nói, đây là một thế giới thực sự linh hoạt, nơi bạn có thể áp dụng các tuỳ chỉnh màu sắc cho ứng dụng của mình.

  • Giờ thì xin mời Jon tiếp tục phần tiếp theo.

Mở rộng độ tin cậy và tốc độ

  • Vâng.

  • Đó là một số điểm linh hoạt khác mà Kirill đã đề cập.

  • Hãy cùng thảo luận về độ tin cậy và tốc độ.

  • Vì vậy, việc xây dựng mã chất lượng cao một cách nhanh chóng là điều mà tất cả nhà phát triển và doanh nghiệp đều mong muốn.

  • Hãy cùng xem Compose đã giúp Play làm việc đó như thế nào.

  • Vì vậy, trước hết, tôi biết sơ đồ này rất lớn, nhưng trước hết, sự đơn giản của cấu trúc mang lại lợi ích to lớn cho tất cả tác giả và người duy trì mã, cả con người và tác nhân.

  • Tôi sẽ không đi quá sâu vào vấn đề này, nhưng một trong những mô hình tư duy mà Compose cố gắng đưa ra là về luồng dữ liệu một chiều và điều này thực sự có tác động lớn đến nhóm của chúng tôi.

  • Đối với những người chưa quen với cách hoạt động của tính năng này, thì về cơ bản, bạn có một nguồn dữ liệu.

  • Nguồn dữ liệu cung cấp dữ liệu.

  • Dữ liệu đó có thể được chuyển đổi thành một giao diện người dùng cụ thể mà chúng ta xuất ra dưới dạng mô hình giao diện người dùng.

  • Sau đó, Compose có thể dễ dàng quan sát điều đó bằng cách gọi một thuộc tính giá trị trên trạng thái đó.

  • Đây là loại mũi tên dọc theo phía trên cùng của sơ đồ này.

  • Sau đó, các sự kiện sẽ diễn ra theo chiều ngược lại.

  • Vì vậy, nếu người dùng nhấp vào một nút, thao tác này sẽ quay lại trình biến đổi giao diện người dùng, cập nhật nguồn dữ liệu, phát ra một giá trị mới, chạy các phép biến đổi và bạn sẽ nhận được vòng lặp này.

  • Vì vậy, mọi thứ đều chạy qua vòng lặp tương đối đơn giản này.

  • Lợi ích mà chúng tôi thực sự nhận thấy từ việc này là giúp giảm thời gian chạy đà.

  • Bạn không cần phải bận tâm về việc tất cả các lệnh gọi này đang diễn ra ở đâu trên luồng chính hoặc ngoài các luồng khác này.

  • Nó tuân theo một vòng lặp chung.

  • Compose giúp việc quan sát dữ liệu trở nên cực kỳ đơn giản và dữ liệu có sự đảm bảo nhất quán mạnh mẽ giữa các lớp cấu trúc.

  • Mô hình tư duy này đã giảm bớt nhiều cuộc trò chuyện về nguồn đáng tin cậy trong nhóm của chúng tôi và loại bỏ hoàn toàn một số loại tình huống tương tranh.

  • Một lợi ích to lớn khác đối với chúng tôi là so với cấu trúc mô hình-khung hiển thị-bộ điều khiển trước đây, việc thực thi song song các nguồn dữ liệu và biến đổi giao diện người dùng trở nên rất đơn giản.

  • Vì vậy, điều này thực sự cải thiện độ trễ tải trong Cửa hàng, bạn biết đấy, hàng chục 50 mili giây hoặc tương tự.

  • Chúng tôi rất ấn tượng.

  • Cùng với luồng dữ liệu một chiều, một yếu tố quan trọng khác của Compose là giao diện người dùng khai báo.

  • Kirill đã đề cập một chút về vấn đề này.

  • Vì vậy, các nhà phát triển trên Play cũng rất thích tính năng này.

  • Luồng điều khiển giao diện người dùng hiện nằm trong một tệp duy nhất.

  • Chúng ta có một ví dụ khá đơn giản ở bên phải.

    @Composable
    fun PurchaseRow(onClick: () -> Unit, modifier: Modifier) {
      Row(modifier) {
        Text("20% off sale")
        if (LocalExpts.current.useButtonV2) {
          ButtonV2("Buy", onClick = onClick)
        } else {
          ButtonV1("Buy", onClick = onClick)
        }
      }
    }
  • Chúng ta sẽ thay đổi giữa hai cách triển khai nút dựa trên cờ thử nghiệm.

  • Thay vì phải đọc nhiều tệp khung hiển thị hoặc tệp mảnh và tệp XML, bạn chỉ cần đọc từ trên xuống dưới và việc này giúp mọi thứ trở nên đơn giản hơn nhiều.

  • Chi phí lồng ghép các composable cũng thấp hơn nhiều so với hệ phân cấp view lồng ghép, đồng thời cho phép chúng tôi sắp xếp mã một cách tự nhiên để dễ đọc hơn, thay vì phải cố gắng tối ưu hoá từng chút một để đạt được hiệu suất.

  • Một lợi ích khác mà chúng tôi nhận thấy là các lệnh gọi lại trong vòng đời đã trở nên đơn giản hơn rất nhiều và số lượng lệnh gọi lại mà bạn cần quan tâm cũng giảm đi.

  • Vì vậy, thay vì có vòng đời của khung hiển thị, vòng đời của fragment, vòng đời của Hoạt động, bạn sẽ có hiệu ứng dùng một lần, tác dụng phụ và tuỳ thuộc vào vị trí bạn đặt, hiệu ứng này sẽ hoạt động theo cách rất nhất quán.

  • Vì vậy, đó là một lợi ích rất lớn đối với chúng tôi.

Chuẩn bị cho LLM

  • Vì vậy, theo tôi, hai thay đổi về cấu trúc này thực sự tạo tiền đề cho LLM và giúp LLM tạo ra mã có chất lượng khá cao.

  • Và tôi chắc rằng nhiều người trong số các bạn có thể đã thử hoặc đã làm việc này với LLM mà bạn yêu thích.

  • Bạn có thể chụp ảnh màn hình có chú thích bằng màu sắc và kiểu chữ rồi đưa vào mô hình để xem, bạn biết đấy, mô hình có thể tạo ra các hàng, cột, văn bản và nút, và nó làm khá tốt.

  • Tuy nhiên, phương pháp này cũng có những điểm hạn chế.

  • Và điều Play thực sự nhận thấy là nó không hiểu toàn bộ mã nguồn của bạn, đúng không?

  • Công cụ này không biết bạn đã tạo những thành phần nào để sử dụng lại, cũng như không biết tên mã thông báo thiết kế.

  • Nó chỉ cung cấp cho bạn các màu và chuỗi được cố định giá trị trong mã.

  • Nội dung nào nên lấy từ thiết bị, nội dung nào nên lấy từ máy chủ, hoặc làm cách nào để đảm bảo hiệu suất khi sử dụng LazyList mà không chỉ tạo một cột lớn?

  • Vì vậy, để giải quyết một số vấn đề này, chúng tôi đã chú thích những ảnh chụp màn hình đó bằng một số siêu dữ liệu khác.

  • Vì vậy, tên giao diện người dùng, hộp giới hạn để chúng ta biết thành phần bắt đầu và kết thúc ở đâu, mã thông báo thiết kế cho tên ngữ nghĩa của màu sắc và kiểu chữ, kỹ năng và một số câu lệnh để cho biết vị trí đặt thành phần này để có thể xem xét các yếu tố về hiệu suất.

  • Và sau đó, bạn cũng chỉ cần một chữ ký hàm cấp cao để có thể cho hệ thống biết nội dung nào là động và nội dung nào là tĩnh.

  • Vì vậy, bạn sẽ có một kết quả tương tự như trước đây, nhưng được chuyển sang sau.

  • Tôi không có các hộp giới hạn ở đây vì nó sẽ làm cho sơ đồ trở nên rối rắm.

  • Nhưng bạn có thể thấy những màu sắc và tên kiểu chữ được cố định giá trị trong mã đó được thay thế bằng tiêu đề lớn và trên nền tảng.

  • Chúng tôi đã đánh dấu rõ ràng tên thành phần như tiêu đề thẻ và huy hiệu biểu tượng.

  • Như vậy, bạn có thể tìm thấy các tệp đó trong toàn bộ mã nguồn của mình.

  • Và đối với chúng tôi, chúng tôi có, bạn biết đấy, rất nhiều trong số này cũng đến từ các thư viện thiết kế phổ biến, mà Kirill sẽ nói đến trong giây lát.

  • Vì vậy, bạn không cần phải luôn gắn nhãn tuỳ chỉnh cho tất cả các sản phẩm này.

  • Bạn kết hợp điều đó với một chữ ký phương thức như chúng ta có ở dưới cùng, OfferCard, và sau đó, nó biết, bạn biết đấy, tiêu đề, endDate, hình ảnh đều là động.

  • Chúng ta không nên được cố định giá trị trong mã cho những giá trị đó.

  • Và cùng với những tên ngữ nghĩa đó, giờ đây, chúng ta có thể hoán đổi thành tất cả các ứng dụng màu sắc khác nhau mà Kirill đã nói đến.

  • Và nhờ đó, chúng tôi tạo ra nhiều mã hơn.

  • Tôi sẽ nhường lời lại cho Kirill để nói về cách chúng tôi duy trì chất lượng.

Tự động hoá chất lượng

  • Phải.

  • Cảm ơn Jon.

  • Vì vậy, tiếp tục chủ đề về LLM và phát triển có sự hỗ trợ của tác nhân, trước tiên chúng ta bắt đầu từ phía thiết kế trải nghiệm người dùng.

  • Điều bạn muốn làm là, bất kể công cụ thiết kế bạn chọn là gì, có thể là Figma hoặc một công cụ khác, bạn nên có một mẫu dùng chung được tất cả nhà thiết kế sử dụng, trong đó có mã thông báo màu, mã thông báo kiểu chữ, mã thông báo hình dạng từ hệ thống thiết kế mà bạn chọn.

  • Có thể là Material.

  • Có thể đó là hệ thống thiết kế tuỳ chỉnh của bạn.

  • Và bạn muốn cụ thể cho các mã thông báo màu, bạn muốn các mẫu đó có hỗ trợ tích hợp để chuyển đổi giữa chế độ sáng và chế độ tối cũng như để chuyển đổi giữa các chế độ tương phản bình thường, trung bình và cao đã được giới thiệu ở cấp Android vài năm trước.

  • Nhờ đó, nhà thiết kế có thể nhanh chóng chuyển đổi giữa các kiểu kết hợp này để xem thông số thiết kế của họ phản hồi như thế nào.

  • Sau đó, khi hoàn tất và bàn giao cho bên triển khai, trong quy trình xuất đó, bạn muốn có một số tính năng để theo dõi rằng mọi màu sắc, mọi thành phần kiểu chữ, mọi hình dạng đều sử dụng mã thông báo phù hợp thay vì giá trị RGB được mã hoá cứng, bộ phông chữ được mã hoá cứng hoặc cỡ chữ được mã hoá cứng.

  • Và cuối cùng, điều chúng tôi thấy rất hữu ích ở quy mô của Google Play là chúng tôi có không chỉ hàng chục mà là vài trăm thành phần, cụm, thẻ, vùng chứa được dùng trên nhiều màn hình.

  • Chúng tôi nhận thấy rằng việc theo dõi tất cả những thông tin này ở một nơi (chúng tôi gọi là danh mục thành phần) là rất hữu ích, sau đó chúng tôi sẽ huấn luyện một tác nhân tuỳ chỉnh dựa trên danh mục thành phần đó.

  • Và tác nhân này sẽ hữu ích khi bạn bắt đầu một màn hình mới, có thể là một hành trình của người dùng mới, có thể là một dòng sản phẩm mới, và từ những khám phá thiết kế ban đầu đó, có thể là trang trình bày, có thể là thông số kỹ thuật của Figma, bạn có thể cung cấp thông tin đó cho tác nhân đó, và tác nhân này sẽ giúp nhanh chóng xác định những thành phần nào đã tồn tại để không cần phải thiết kế lại và xác định lại thông số kỹ thuật, nhờ đó không cần phải triển khai lại từ đầu.

  • Và điều đó giúp giảm đáng kể chi phí thiết kế và chi phí triển khai.

  • Về mặt triển khai, chúng tôi dựa rất nhiều vào các quy tắc Lint cốt lõi và tuỳ chỉnh.

  • Một số quy tắc Lint cốt lõi mà tôi muốn đề cập là FrequentlyChangingValueDetector giúp xác định các nguồn của quá trình tái cấu trúc không cần thiết, có thể dẫn đến độ trễ và hiện tượng giật, và một quy tắc khác là ScaffoldPaddingDetector để gắn cờ các trường hợp chúng ta sử dụng thành phần kết hợp Scaffold của Material Compose nhưng bỏ qua khoảng đệm sắp tới.

  • Đây không phải là nguồn gây ra độ trễ và hiện tượng giật, nhưng trong một số trường hợp, nó có thể dẫn đến việc bố cục bị lệch, rất khó gỡ lỗi, chẳng hạn như trong một số trường hợp như tràn viền hoặc gập, mở.

  • Và cuối cùng, BoxWithConstraints, đi kèm với một số điểm cần cân nhắc về hiệu suất.

  • Có thể mất hai khung hình để bố trí mọi thứ đúng cách.

  • Chúng tôi không chặn hoàn toàn, nhưng chúng tôi gắn cờ cảnh báo Lint để nhà phát triển đang làm việc trên màn hình cụ thể đó biết rằng họ đang đưa ra lựa chọn cụ thể để sử dụng BoxWithConstraints, hoặc có thể họ có thể chọn sử dụng một thứ khác cho bố cục cụ thể đó.

  • Đối với tính năng tự động hoá giao diện, một lần nữa, mã thông báo màu, mã thông báo kiểu chữ, mã thông báo hình dạng.

  • Chúng tôi có một quy tắc tìm lỗi mã nguồn chặn việc sử dụng màu sắc và kiểu chữ được cố định giá trị trong mã.

  • Chúng tôi có một quy tắc tìm lỗi mã nguồn gắn cờ việc sử dụng các thành phần Material 2.

  • Chúng tôi chỉ muốn sử dụng Material 3, phiên bản mới nhất và tốt nhất, bao gồm cả các thành phần biểu cảm mới được giới thiệu vào năm ngoái và năm nay.

  • Chúng tôi muốn có một quy tắc Lint tuỳ chỉnh để ngăn người dùng đọc màu từ các tệp XML cũ.

  • Chúng tôi muốn ưu tiên Compose và chỉ dùng Compose cho các màn hình mới.

  • Và các thành phần kết hợp Văn bản, cụ thể là trong hệ thống thiết kế Material Design, có các phương án dự phòng cho kiểu và màu sắc.

  • Các thành phần này đọc màu sắc và kiểu chữ từ nội dung cục bộ, nhưng chúng ta không muốn dựa vào đó.

  • Chúng tôi muốn mọi văn bản đều sử dụng kiểu cụ thể, kiểu chữ và màu sắc cụ thể từ thông số thiết kế.

  • Đó là một quy tắc tìm lỗi mã nguồn mà chúng tôi có.

  • Và cuối cùng, tương tự như ScaffoldPaddingDetector, chúng tôi có một quy tắc Lint tuỳ chỉnh để đảm bảo rằng mọi hàm Composable đều sử dụng đối tượng sửa đổi đầu vào.

  • Một lần nữa, để ngăn chặn, bạn biết đấy, các cách sử dụng mới bị đặt không chính xác hoặc không tôn trọng nền tảng sắp tới hoặc bất kể điều gì có thể xảy ra.

Kết luận

  • Và đây là 3 điểm chính mà chúng tôi muốn bạn ghi nhớ sau bài thuyết trình này.

  • Thứ nhất, tính đến cuối năm 2026, chúng tôi cho rằng Compose là một bộ công cụ giao diện người dùng hoàn thiện, đã được chứng minh ở quy mô lớn.

  • Bản thân Android cũng ưu tiên Compose.

  • Đầu năm nay tại Google I/O, chúng tôi đã thông báo rằng tất cả thư viện giao diện người dùng và tất cả luồng tác nhân đều ưu tiên Compose.

  • Và như Jon đã đề cập trước đó trong bản trình bày, hãy thu thập dữ liệu, đi, chạy bộ và chạy, chúng tôi khuyên bạn nên di chuyển dần dần, đặc biệt là các toàn bộ mã nguồn lớn, để tăng tốc độ cho luồng nhà phát triển và luồng tác nhân.

  • Đến đây, chúng tôi xin cảm ơn các bạn đã dành thời gian tham gia buổi hôm nay. Trong vài phút nữa, tôi và Jon sẽ ra ngoài để giải đáp mọi thắc mắc của các bạn.

  • Một lần nữa, cảm ơn bạn đã dành thời gian.

Mã

Đoạn mã

Đoạn mã Kotlin ở phút 16:09 trong video "Mở rộng quy mô về độ tin cậy và tốc độ"
@Composable
fun PurchaseRow(onClick: () -> Unit, modifier: Modifier) {
  Row(modifier) {
    Text("20% off sale")
    if (LocalExpts.current.useButtonV2) {
      ButtonV2("Buy", onClick = onClick)
    } else {
      ButtonV1("Buy", onClick = onClick)
    }
  }
}