đồ án 2 xây dựng ứng dụng chia sẻ công thức món ăn

108 1 0
Tài liệu đã được kiểm tra trùng lặp
đồ án 2 xây dựng ứng dụng chia sẻ công thức món ăn

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Bằng cách sử dụng Compose, bạn có thể xây dựng giao diện người dùng bằng cách xác định một tập hợp các hàm có khả năng kết hợp lấy dữ liệu và cung cấp các thành phần trên giao diện người

Trang 1

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN KHOA CÔNG NGHỆ PHẦN MỀM

- -

BÁO CÁO ĐỒ ÁN 2 Đề tài:

XÂY DỰNG ỨNG DỤNG CHIA SẺ CÔNG THỨC MÓN ĂN

Giảng viên hướng dẫn: ThS Huỳnh Tuấn Anh Lớp: SE122.O11

Trang 3

LỜI CẢM ƠN

Sau quá trình học tập và rèn luyện tại khoa Công nghệ phần mềm trường Đại học Công nghệ Thông tin – ĐHQG TP.HCM, em đã được trang bị các kiến thức cơ bản cùng các kỹ năng thực tế để có thể hoàn thành Đồ án 2 của mình

Để hoàn thành đồ án này, với lòng biết ơn sâu sắc em xin gửi lời cảm ơn chân thành đến:

Ban Giám hiệu trường Đại học Công nghệ Thông tin – ĐHQG TP.HCM vì đã tạo điều kiện thuận lợi để sinh viên tìm kiếm, nghiên cứu thông tin với hệ thống thư viện hiện đại, đa dạng các loại sách và tài liệu

Gần gũi hơn là những lời tốt đẹp nhất xin gửi đến đến thầy Nguyễn Công Hoan đã tận tình giúp đỡ, định hướng cách tư duy và hướng làm việc khoa học Đó là những góp ý hết sức quý báu không chỉ trong quá trình thực hiện đồ án mà còn là hành trang tiếp bước cho em trong quá trình học tập và làm việc sau này

Sau cùng, xin chúc quý Thầy Cô trong khoa Công nghệ Phần mềm nói riêng cũng như các giáo viên tại trường Công nghệ thông tin nói chung thật dồi dào sức khỏe, niềm tin để tiếp tục thực hiện sứ mệnh cao đẹp của mình

Thành phố Hồ Chí Minh, tháng 12 năm 2023 Sinh Viên

Bùi Lê Hoài An

Trang 4

NHẬN XÉT CỦA GIẢNG VIÊN

Trang 5

MỤC LỤC

LỜI CẢM ƠN 3

NHẬN XÉT CỦA GIẢNG VIÊN 4

MỤC LỤC 5

CHƯƠNG 1: GIỚI THIỆU TỔNG QUAN 9

1.Thông tin sinh viên: 9

2.Tổng quan đề tài: 9

2.1Giới thiệu đề tài: 9

2.2Phạm vi nghiên cứu: 9

2.3Nội dung nghiên cứu: 9

2.4Kết quả hướng tới: 10

3.Công cụ sử dụng: 10

CHƯƠNG 2: CÔNG NGHỆ SỬ DỤNG 11

1.Giới thiệu ngôn ngữ lập trình Kotlin 11

2.Jetpack Compose 11

3.Tại sao lại là Jetpack Compose? 12

4.Mô hình tư duy trong Jetpack Compose 12

4.1.Mô hình lập trình khai báo 13

4.2.Hàm composable đơn giản 13

4.3.Thay đổi mô hình khai báo 15

4.4.Nội dung động 17

4.5.Recomposition 18

4.5.1.Các hàm composable có thể thực thi theo thứ tự bất kỳ 19

4.5.2.Các hàm composable có thể chạy song song 19

Trang 6

5.4.Mô hình bố cục 27

5.5.Hiệu suất 29

5.6.Sử dụng modifiers 29

6.Quản lý trạng thái 30

6.1.Trạng thái và composition 31

6.2.Trạng thái trong composition 32

6.3.Chuyển trạng thái lên trên 33

6.4.Khôi phục trạng thái 36

6.4.1.Parcelize 36

6.4.2.MapSaver 37

6.5.Phần tử giữ trạng thái 37

6.6.Kích hoạt lại tính năng ghi nhớ các tính toán khi khoá thay đổi 37

7.Vòng đời của Composable 39

7.1.Tổng quan 39

7.2.Phân tích một Composable trong Composition 41

7.2.1.Thêm thông tin hỗ trợ quá trình recomposition 42

7.3.Bỏ qua nếu giá trị đầu vào không thay đổi 46

8.Các giai đoạn trong Jetpack Compose 47

8.1.3 giai đoạn của một frame 47

8.2.Đọc trạng thái 49

8.3.Đọc trạng thái theo giai đoạn 50

8.3.1.Giai đoạn 1: Composition 50

8.3.2.Giai đoạn 2: Layout 50

8.3.3.Giai đoạn 3: Drawing 51

8.4.Tối ưu hóa việc đọc trạng thái 52

8.5.Vòng lặp tái kết hợp (phần phụ thuộc giai đoạn tuần hoàn) 54

Trang 7

1.3.Đối tượng hướng đến 59

1.4.Môi trường phát triển ứng dụng 59

1.5.Kết quả mong đợi 60

1.6.Quy trình thực hiện các công việc chính 60

2.Phân tích, thiết kế hệ thống 60

2.1.Xác định và mô hình hóa các yêu cầu phần mềm 60

2.1.1.Xác định yêu cầu 60

2.1.1.1 Một số yêu cầu phần mềm phải có 60

2.1.1.2 Ràng buộc logic ban đầu 61

2.2.Thiết kế hệ thống 77

2.2.1.Kiến trúc hệ thống: Multi module architecture 77

2.2.1.1 Vấn đề về độ lớn của mã 77

2.2.1.2 Module hóa 77

2.2.2.Kiến trúc ứng dụng 78

2.3.Thiết kế dữ liệu 80

2.4.Thiết kế giao diện 85

2.4.1.Sơ đồ liên kết màn hình 85

2.4.2.Danh sách các màn hình 86

3.Cài đặt và thử nghiệm 105

Trang 9

CHƯƠNG 1: GIỚI THIỆU TỔNG QUAN

1 Thông tin sinh viên:

20520985 Bùi Lê Hoài An 20520985@gm.uit.edu.vn

2 Tổng quan đề tài:

Chúng ta không thể phủ nhận sự hữu ích của các framework platform (Flutter, React-Native, …) đã giúp chúng ta phần nào giải quyết được vấn đề về mặt thời gian Tuy vậy khi nhìn vào thực tế, các công ty lớn trên thế giới tiếp tục sử dụng các ứng dụng native, đó là vấn đề lớn cũng cần phải được kể đến: hiệu suất Hiệu suất ảnh hưởng trực tiếp đến trải nghiệm người dùng Vì thế phát triển ứng dụng

coss-Phát triển ứng dụng native từ lâu đã tồn tại những yếu điểm dễ dàng nhận thấy Đơn cử như đối với Android, đó là việc nhà phát triển phải sử dụng một loại ngôn ngữ khác hoàn toàn với ngôn ngữ chính để lập trình – XML Đối với các nhà phát triển cũng như các công ty phải học song song 2 ngôn ngữ (Java/Kotlin và XML) là rất mất thời gian, dẫn đến đó là tiêu tốn nhiều chi phí

Kể từ sau Google I/O 2019, Kotlin dần phát triển để thay thế Java, trở thành một ngôn ngữ lập trình được ưa chuộng nhất cho phát triển ứng dụng Android native Và điều chúng ta mong muốn nhất rồi cũng đến: Jetpack Compose, sử dụng Kotlin làm ngôn ngữ lập trình đã ra đời với nhiệm vụ tiên quyết: source code chỉ chứa duy nhất 1 ngôn ngữ lập trình

Trang 10

Em sẽ tiến hành nghiên cứu chi tiết về cách thức hoạt động, ưu - khuyết điểm cũng như các thư viện - tính năng - package liên quan đến Compose

Với đề tài này, em đề ra hai mục tiêu chính:

• Đối với các nhân: mở rộng kiến thức của mình về Compose thông qua quá trình tìm hiểu và áp dụng vào ứng dụng thực tế Các kiến thức tìm hiểu được thông qua đồ án thúc đẩy em phát triển thêm các ứng dụng khác bằng Compose Jetpack Đồng thời, em học được cách nghiên cứu và sử dụng một framework mới cần trải qua quá trình gì nhằm giúp em dễ dàng tiếp xúc với các công nghệ mới hơn trong tương lai

• Có cái nhìn tổng quát hơn trong việc ứng dụng Machine Learning trong phát triển ứng dụng mobile

3 Công cụ sử dụng:

Trong quá trình xây dựng phần mềm, em đã sử dụng các phần mềm sau:

• Android Studio: phát triển front end • Google Colabs: training model • GitHub: quản lý source code

Trang 11

CHƯƠNG 2: CÔNG NGHỆ SỬ DỤNG

1 Giới thiệu ngôn ngữ lập trình Kotlin

Kotlin là một ngôn ngữ lập trình đa năng, được thiết kế để chạy trên nền tảng Java Virtual Machine (JVM), nhưng cũng có thể chạy trên nền tảng Android, JavaScript và Native Kotlin được phát triển bởi JetBrains, cùng với một số cộng đồng lập trình viên đóng góp

Một số đặc điểm của Kotlin bao gồm:

• Kotlin là một ngôn ngữ lập trình hướng đối tượng (OOP) và hỗ trợ các khái niệm lập trình hàm (FP), giúp cho việc phát triển ứng dụng linh hoạt hơn • Kotlin có cú pháp đơn giản, dễ đọc và dễ viết hơn so với Java và nhiều

Kotlin đã được Google chính thức công nhận là ngôn ngữ lập trình cho phát triển ứng dụng Android, và được sử dụng rộng rãi trong cộng đồng lập trình viên Android Ngoài ra, Kotlin cũng được sử dụng trong nhiều dự án khác, bao gồm phát triển trên máy chủ, ứng dụng web và phát triển ứng dụng trên các thiết bị nhúng

2 Jetpack Compose

Jetpack Compose là một thư viện UI cho phép bạn xây dựng giao diện người dùng Android bằng cách sử dụng Kotlin Nó cho phép tạo các giao diện người dùng tùy chỉnh và linh hoạt hơn Bạn có thể tạo các giao diJetpack Compose là một framework để phát triển giao diện người dùng (UI) trên nền tảng Android, được phát triển bởi Google Nó cho phép lập trình viên tạo giao diện người dùng bằng

Trang 12

3 Tại sao lại là Jetpack Compose?

• Khai báo giao diện người dùng: Jetpack Compose sử dụng phong cách lập trình khai báo, cho phép bạn xác định giao diện bằng cách chỉ định những gì bạn muốn nó hiển thị, thay vì xác định cách để đạt được nó Điều này làm cho mã dễ đọc, dễ hiểu hơn và dễ bảo trì hơn so với phương pháp truyền thống sử dụng XML

• Dễ dàng tích hợp: Jetpack Compose tích hợp tốt với các thành phần và công nghệ hiện có của Android, cho phép bạn sử dụng các tính năng mạnh mẽ khác như ViewModel, LiveData và Room để quản lý trạng thái ứng dụng và tương tác với cơ sở dữ liệu

• Hiệu suất cao hơn: Jetpack Compose được tối ưu để cung cấp hiệu suất cao hơn so với phương pháp truyền thống Compose sử dụng một cơ chế gọi là "Recompose" để chỉ cập nhật lại các phần tử giao diện người dùng đã thay đổi thay vì cập nhật toàn bộ giao diện Điều này giúp giảm tải cho CPU và cải thiện hiệu suất của ứng dụng

• Tương thích và tái sử dụng tốt hơn: Jetpack Compose được thiết kế để tương thích với các phiên bản Android cũ hơn và mới hơn Bạn có thể sử dụng Compose trong các dự án hiện có hoặc tích hợp nó với mã Java/Kotlin truyền thống Ngoài ra, Jetpack Compose cũng khuyến khích tái sử dụng mã và các thành phần giao diện người dùng, giúp tiết kiệm thời gian và công sức trong quá trình phát triển

• Cộng đồng mạnh mẽ: Jetpack Compose đã nhận được sự hỗ trợ rất lớn từ cộng đồng phát triển Android Có nhiều tài liệu, ví dụ mã và nguồn tài nguyên hữu ích được chia sẻ trên trang web của Google và từ các nhà phát triển khác trên Internet Bạn cũng có thể nhận được sự hỗ trợ từ cộng đồng qua các diễn đàn, nhóm Facebook, và các nhóm Telegram

Tổng thể, Jetpack Compose là một framework mạnh mẽ và tiện ích cho việc phát triển giao diện người dùng Android Nó giúp bạn tăng năng suất, cải thiện hiệu suất ứng dụng và tạo ra giao diện linh hoạt, tương tác

4 Mô hình tư duy trong Jetpack Compose

Jetpack Compose là bộ công cụ khai báo giao diện người dùng hiện đại cho Android Compose sẽ giúp bạn dễ dàng ghi và duy trì giao diện người dùng ứng dụng bằng cách cung cấp API khai báo cho phép bạn hiển thị giao diện người dùng

Trang 13

của ứng dụng mà không cần ra lệnh thay đổi các chế độ xem giao diện người dùng Thuật ngữ này cần được giải thích đôi chút nhưng có ý nghĩa rất quan trọng đối với cách thiết kế ứng dụng của bạn

4.1 Mô hình lập trình khai báo

Trước đây, hệ phân cấp chế độ xem Android được biểu thị dưới dạng cây tiện ích giao diện người dùng Khi trạng thái của ứng dụng thay đổi vì những yếu tố như hoạt động tương tác của người dùng, bạn cần cập nhật hệ thống phân cấp giao diện người dùng để hiển thị dữ liệu hiện tại Cách phổ biến nhất để cập nhật giao diện người dùng là hướng dẫn cho cây bằng các hàm như findViewById() và thay đổi các nút bằng những phương thức gọi như button.setText(String), container.addChild(View) hoặc img.setImageBitmap(Bitmap) Các phương thức này thay đổi trạng thái nội bộ của tiện ích

Việc điều chỉnh chế độ xem theo cách thủ công sẽ làm tăng khả năng xảy ra lỗi Nếu một phần dữ liệu hiển thị ở nhiều vị trí thì bạn sẽ có thể quên cập nhật một trong các chế độ xem hiển thị dữ liệu đó Việc tạo các trạng thái không hợp lệ cũng rất dễ xảy ra khi hai lượt cập nhật xung đột theo cách không mong đợi Ví dụ: một lượt cập nhật có thể cố gắng đặt một giá trị nút vừa mới bị xoá khỏi giao diện người dùng Nói chung, độ phức tạp của việc bảo trì phần mềm tăng lên cùng với số chế độ xem cần cập nhật

Trong vài năm qua, toàn bộ ngành đã bắt đầu chuyển sang mô hình giao diện người dùng khai báo, giúp đơn giản hoá rất nhiều kỹ thuật liên quan đến việc xây dựng và cập nhật giao diện người dùng Kỹ thuật này hoạt động bằng cách tạo lại từ đầu toàn bộ màn hình, sau đó chỉ áp dụng những thay đổi cần thiết Phương pháp này giúp bạn dễ dàng cập nhật hệ phân cấp chế độ xem có trạng thái theo cách thủ công Compose là một khung giao diện người dùng khai báo

Một khó khăn trong việc tạo lại toàn bộ màn hình là giải pháp này có thể tốn

Trang 14

Bằng cách sử dụng Compose, bạn có thể xây dựng giao diện người dùng bằng cách xác định một tập hợp các hàm có khả năng kết hợp lấy dữ liệu và cung cấp các thành phần trên giao diện người dùng Một ví dụ đơn giản là hàm Greeting lấy String và cung cấp Text hiển thị tin nhắn chào mừng

Hình 1 Một hàm có khả năng kết hợp đơn giản được chuyển dữ liệu và sử dụng dữ

liệu này để hiển thị một tiện ích văn bản trên màn hình Vài điều đáng chú ý về hàm này:

• Hàm này được chú thích bằng chú thích @Composable Tất cả hàm có khả năng kết hợp đều phải có chú thích này; chú thích này sẽ thông báo cho trình biên dịch Compose rằng hàm này có mục đích chuyển đổi dữ liệu thành giao diện người dùng

• Hàm này lấy dữ liệu Các hàm có khả năng kết hợp có thể chấp nhận các thông số cho phép logic của ứng dụng mô tả giao diện người dùng Trong trường hợp này, tiện ích của chúng tôi chấp nhận String để có thể chào người dùng theo tên

• Hàm này hiển thị văn bản trong giao diện người dùng Hàm này thực hiện tính năng này bằng cách gọi hàm có khả năng kết hợp Text() - hàm thực sự tạo ra thành phần văn bản trên giao diện người dùng Hàm có khả năng kết hợp cung cấp sự phân cấp giao diện người dùng bằng cách gọi các hàm có khả năng kết hợp khác

Trang 15

• Hàm này không trả về bất kỳ giá trị nào Các hàm Compose cung cấp giao diện người dùng không cần trả về bất cứ điều gì vì các hàm này mô tả trạng thái màn hình mong muốn thay vì tạo các tiện ích giao diện người dùng • Hàm này nhanh chóng, không thay đổi giá trị và không có tác dụng phụ • Hàm này hoạt động theo cách tương tự như khi được gọi nhiều lần với cùng

một đối số và không sử dụng các giá trị khác như biến toàn cục hoặc lệnh gọi đến random()

• Hàm này mô tả giao diện người dùng mà không để lại bất kỳ tác dụng phụ nào, chẳng hạn như sửa đổi các thuộc tính hoặc biến toàn cục

Nhìn chung, bạn phải viết tất cả các hàm có khả năng kết hợp bằng các thuộc tính này vì những lý do được thảo luận trong phần kết hợp lại

4.3 Thay đổi mô hình khai báo

Với nhiều bộ công cụ giao diện người dùng hướng đối tượng bắt buộc, bạn khởi chạy giao diện người dùng bằng cách tạo một cây tiện ích Bạn thường thực hiện việc này bằng cách tăng cường một tệp bố cục XML Mỗi tiện ích duy trì một trạng thái nội bộ riêng và hiển thị các phương thức getter và setter cho phép logic ứng dụng tương tác với tiện ích đó

Trong phương pháp khai báo của Compose, các tiện ích tương đối không có trạng thái và không hiển thị các hàm setter hoặc getter Trên thực tế, các tiện ích không xuất hiện dưới dạng đối tượng Bạn cập nhật giao diện người dùng bằng cách gọi cùng một hàm có khả năng kết hợp với các đối số khác nhau Việc này giúp bạn dễ dàng cung cấp trạng thái cho các mẫu kiến trúc, chẳng hạn như ViewModel, như mô tả trong Hướng dẫn về cấu trúc ứng dụng Sau đó, các yếu tố có thể kết hợp sẽ chịu trách nhiệm chuyển đổi trạng thái ứng dụng hiện tại thành giao diện người dùng mỗi khi cập nhật dữ liệu có thể quan sát

Trang 16

Hình 2: Logic của ứng dụng cung cấp dữ liệu cho hàm có khả năng kết hợp cấp

cao nhất Hàm đó sử dụng dữ liệu để mô tả giao diện người dùng bằng cách gọi các yếu tố có thể kết hợp khác và chuyển dữ liệu thích hợp cho các yếu tố có thể kết hợp đó và xuống hệ thống phân cấp

Khi người dùng tương tác với giao diện người dùng, giao diện người dùng sẽ

đưa ra các sự kiện như onClick Những sự kiện đó sẽ thông báo cho logic ứng

dụng, qua đó có thể thay đổi trạng thái của ứng dụng Khi trạng thái thay đổi, các hàm có khả năng kết hợp được gọi lại bằng dữ liệu mới Việc này khiến các thành phần trên giao diện người dùng được vẽ lại–quy trình này được gọi là

recomposition

Trang 17

Hình 3 Người dùng tương tác với một thành phần trên giao diện người dùng,

khiến sự kiện được kích hoạt Logic của ứng dụng phản hồi sự kiện, sau đó các hàm có khả năng kết hợp sẽ tự động được gọi lại bằng các thông số mới (nếu cần)

4.4 Nội dung động

Vì các hàm có khả năng kết hợp được viết bằng Kotlin thay vì XML nên các hàm này có thể linh động như mọi mã Kotlin khác Ví dụ: giả sử bạn muốn tạo giao diện người dùng chào đón một danh sách người dùng:

Trang 18

4.5 Recomposition

Trong mô hình giao diện người dùng bắt buộc, để thay đổi một tiện ích, bạn phải gọi một phương thức setter trên tiện ích đó để thay đổi trạng thái nội bộ của phương thức đó Trong Compose, bạn gọi lại hàm có khả năng kết hợp với dữ liệu mới Cách làm này sẽ giúp vẽ lại hàm được kết hợp lại–các tiện ích do hàm cung cấp (nếu cần) cùng với dữ liệu mới Khung Compose có thể chỉ kết hợp lại các thành phần đã thay đổi một cách thông minh

Ví dụ: hãy xem xét hàm có khả năng kết hợp hiển thị một nút này:

Hình 5

Mỗi khi người dùng nhấp vào nút này, trình gọi sẽ cập nhật giá trị của clicks Compose gọi lambda bằng hàm Text để hiển thị giá trị mới; quy trình này được gọi là kết hợp lại Các hàm khác không phụ thuộc vào giá trị không được kết hợp lại

Như chúng ta đã thảo luận, việc kết hợp lại toàn bộ cây giao diện người dùng có thể sẽ tốn kém vì sẽ mất thêm công suất tính toán và thời lượng pin Compose giải quyết vấn đề này thông qua phương thức kết hợp lại thông minh sau

Kết hợp lại là quá trình gọi lại các hàm có khả năng kết hợp khi giá trị nhập thay đổi Quá trình này được thực hiện khi dữ liệu đầu vào của hàm thay đổi Khi Compose kết hợp lại dựa trên dữ liệu nhập mới, công cụ này chỉ gọi các hàm hoặc lambda có thể đã thay đổi và bỏ qua các yếu tố còn lại Bằng cách bỏ qua tất cả các hàm hoặc lambda không có thông số được thay đổi, Compose có thể kết hợp lại một cách hiệu quả

Không phụ thuộc vào tác dụng phụ của việc thực thi các hàm có khả năng kết hợp vì việc kết hợp lại một hàm có thể bị bỏ qua Nếu bạn thực hiện điều này, người dùng có thể gặp phải hành vi lạ và không thể đoán trước trong ứng dụng Tác dụng phụ là bất kỳ thay đổi nào hiển thị với phần còn lại của ứng dụng Ví dụ: những hành động sau đây đều là tác dụng phụ nguy hiểm:

• Ghi vào thuộc tính của đối tượng dùng chung • Cập nhật giá trị có thể quan sát trong ViewModel

Trang 19

• Cập nhật các tuỳ chọn dùng chung

Các hàm có khả năng kết hợp có thể được thực thi lại thường xuyên trong mỗi khung hình, chẳng hạn như khi hệ thống hiển thị một ảnh động Các hàm có khả năng kết hợp phải nhanh chóng để tránh bị giật trong ảnh động Nếu bạn cần thực hiện các thao tác tốn kém, chẳng hạn như đọc từ các tuỳ chọn dùng chung, hãy thực hiện việc này trong coroutine trong nền và chuyển giá trị kết quả đến hàm có khả năng kết hợp dưới dạng thông số

Các phần sau đây sẽ trình bày cách tạo hàm có khả năng kết hợp để hỗ trợ quá trình kết hợp lại Trong mọi trường hợp, phương pháp hay nhất là đảm bảo các hàm có khả năng kết hợp chạy nhanh, không thay đổi giá trị và không có tác dụng phụ

4.5.1 Các hàm composable có thể thực thi theo thứ tự bất kỳ

Nếu kiểm tra mã cho một hàm có khả năng kết hợp, bạn có thể giả định rằng mã được chạy theo thứ tự nó xuất hiện Tuy nhiên, điều này không nhất thiết đúng Nếu một hàm có khả năng kết hợp chứa lệnh gọi đến các hàm có khả năng kết hợp khác thì các hàm đó có thể chạy theo thứ tự bất kỳ Bạn có thể dùng Compose để nhận diện một số thành phần trên giao diện người dùng có mức độ ưu tiên cao hơn các thành phần khác và vẽ ra các thành phần đó trước

Ví dụ: giả sử bạn có mã như sau để vẽ 3 màn hình trong một bố cục thẻ:

Các lệnh gọi đến StartScreen, MiddleScreen và EndScreen có thể xuất hiện theo thứ tự bất kỳ Điều này có nghĩa là bạn không thể để StartScreen() đặt một số

Trang 20

chạy các hàm có khả năng kết hợp không có trên màn hình ở mức độ ưu tiên thấp hơn

Tính năng tối ưu hoá này có nghĩa là một hàm có khả năng kết hợp có thể thực thi trong một nhóm các chuỗi nền Nếu một hàm có khả năng kết hợp gọi một hàm trên ViewModel thì Compose có thể gọi hàm đó từ nhiều chuỗi cùng lúc

Để đảm bảo ứng dụng hoạt động chính xác, tất cả hàm có khả năng kết hợp không được có tác dụng phụ Thay vào đó, hãy kích hoạt các tác dụng phụ của lệnh gọi lại, chẳng hạn như onClick luôn thực thi trên chuỗi giao diện người dùng

Khi một hàm có khả năng kết hợp được gọi, lệnh gọi có thể xảy ra trên một chuỗi khác với phương thức gọi Điều đó có nghĩa là bạn nên tránh sử dụng mã sửa đổi các biến dưới dạng lambda có thể kết hợp vì loại mã này không an toàn cho chuỗi và vì đây là một tác dụng phụ không thể chấp nhận được của lambda có thể kết hợp

Sau đây là ví dụ về một composable cho thấy danh sách và số lượng:

Mã này không có tác dụng phụ và chuyển đổi danh sách nhập vào giao diện người dùng Đây là mã lý tưởng cho việc hiển thị một danh sách nhỏ Tuy nhiên, nếu hàm này ghi vào một biến cục bộ thì mã này sẽ không đúng hoặc không an toàn cho chuỗi:

Trang 21

Ở ví dụ này, items được sửa đổi với các thành phần kết hợp lại Đó có thể là mọi khung ảnh động hoặc khi danh sách cập nhật Dù là điều nào thì giao diện người dùng cũng sẽ hiển thị số lượng không chính xác Do đó, cách ghi này sẽ không được hỗ trợ trong Compose, với việc cấm các cách ghi đó, chúng tôi cho phép khung thay đổi các chuỗi thực thi lambda có thể kết hợp

4.5.3 Bỏ qua recomposition nhiều nhất có thể

Khi các phần trong giao diện người dùng của bạn không hợp lệ, Compose sẽ cố gắng hết sức để kết hợp lại các phần cần cập nhật Điều này có nghĩa là công cụ này có thể bỏ qua để chạy lại thành phần có thể kết hợp của một nút mà không cần thực thi bất kỳ thao tác có thể kết hợp nào ở trên hoặc bên dưới trong cây giao diện người dùng

Mọi hàm và lambda có khả năng kết hợp đều có thể tự phân tích lại Sau đây là ví dụ minh họa cách việc kết hợp lại có thể bỏ qua một số phần tử khi hiển thị một danh sách:

Trang 22

Mỗi phạm vi này có thể là nội dung duy nhất cần thực thi trong quá trình kết hợp lại Compose có thể bỏ qua cho đến lambda Column mà không cần thực thi bất kỳ yếu tố gốc nào của yếu tố này khi header thay đổi Và khi thực thi Column, Compose có thể chọn bỏ qua các mục của LazyColumn nếu names không thay đổi

Xin nhắc lại, việc thực thi tất cả hàm hoặc lambda có khả năng kết hợp không được có tác dụng phụ Khi bạn cần thực hiện tác dụng phụ, hãy kích hoạt từ lệnh gọi lại

4.5.4 Recomposition là khả quan

Việc kết hợp lại bắt đầu lại bất cứ khi nào Compose cho rằng các thông số của một thành phần có thể kết hợp có thể đã thay đổi Việc kết hợp lại là khả quan, nghĩa là Compose sẽ hoàn thành việc kết hợp lại trước khi các thông số thay đổi lần nữa

Trang 23

Nếu một thông số thay đổi trước khi quá trình kết hợp lại hoàn tất thì Compose có thể sẽ hủy quá trình kết hợp lại đó và bắt đầu lại bằng thông số mới

Khi quá trình kết hợp lại bị hủy, Compose sẽ loại bỏ cây giao diện người dùng khỏi quá trình kết hợp lại Nếu bạn có bất kỳ tác dụng phụ nào phụ thuộc vào giao diện người dùng đang hiển thị thì tác dụng phụ này sẽ được áp dụng ngay cả khi quá trình kết hợp lại bị hủy Điều này có thể làm cho trạng thái ứng dụng không nhất quán

Hãy đảm bảo rằng tất cả hàm và lambda có khả năng kết hợp đều giống nhau và không có tác dụng phụ khi xử lý việc kết hợp lại một cách khả quan

4.5.5 Các hàm có khả năng recomposition có thể chạy khá thường xuyên

Trong một số trường hợp, một hàm có khả năng kết hợp có thể chạy cho mọi khung giao diện người dùng Nếu thực hiện các thao tác tốn kém (chẳng hạn như đọc từ bộ nhớ của thiết bị) thì hàm này có thể khiến giao diện người dùng bị giật

Ví dụ: nếu tiện ích cố gắng đọc chế độ cài đặt của thiết bị thì tiện ích đó có thể đọc chế độ cài đặt hàng trăm lần mỗi giây và gây ra ảnh hưởng tiêu cực đến hiệu suất của ứng dụng

Nếu hàm có khả năng kết hợp của bạn cần dữ liệu thì hàm đó phải xác định các thông số cho dữ liệu Sau đó, bạn có thể chuyển thao tác tốn kém sang một chuỗi khác, bên ngoài thành phần kết hợp và chuyển dữ liệu sang Compose bằng

mutableStateOf hoặc LiveData

5 Bố cục Compose cơ bản 5.1 Mục tiêu

Việc triển khai hệ thống bố cục trong Jetpack Compose có hai mục tiêu chính: • Hiệu suất cao

Trang 24

Hàm có khả năng kết hợp là khối xây dựng cơ bản trong Compose Hàm có khả năng kết hợp là một hàm chèn Unit mô tả một số phần trên giao diện người dùng Hàm sử dụng một số dữ liệu đầu vào và tạo nội dung hiển thị trên màn hình Để biết thêm thông tin về các thành phần kết hợp, hãy xem tài liệu Mô hình tư duy của Compose

Một hàm có khả năng kết hợp có thể chuyển phát nhiều thành phần trên giao diện người dùng Tuy nhiên, nếu bạn không đưa ra cách sắp xếp, thì Compose có thể sắp xếp các thành phần theo cách mà bạn không muốn Ví dụ: mã này tạo ra hai thành phần văn bản:

Nếu bạn không hướng dẫn cách sắp xếp các thành phần này, thì công cụ Compose sẽ xếp chồng các thành phần văn bản lên nhau, khiến cho chúng không thể đọc được:

Compose cung cấp một tập hợp các bố cục sẵn sàng sử dụng để giúp bạn sắp xếp các thành phần trên giao diện người dùng và giúp bạn dễ dàng xác định các bố cục của riêng mình, ở mức độ chuyên biệt cao hơn

5.3 Các bố cục cơ bản

Trong nhiều trường hợp, bạn chỉ cần sử dụng Các thành phần của bố cục tiêu chuẩn trong Compose

Hãy dùng Column để đặt các mục theo chiều dọc trên màn hình

Trang 25

Tương tự, hãy dùng Row để đặt các mục theo chiều ngang trên màn hình Cả hai mã Column và Row đều hỗ trợ định cấu hình căn chỉnh các thành phần có trong

Sử dụng Box để xếp các thành phần chồng lên nhau Box cũng hỗ trợ định cấu

hình căn chỉnh cụ thể các thành phần có trong mã

Trang 26

Thông thường, các khối xây dựng này là tất cả những gì bạn cần Bạn có thể viết hàm có khả năng kết hợp của riêng mình để kết hợp các bố cục này vào một bố cục chi tiết hơn phù hợp với ứng dụng của bạn

Lưu ý: Compose xử lý hiệu quả các bố cục lớp lồng nhau, khiến chúng trở

thành một cách tuyệt vời để thiết kế giao diện người dùng phức tạp Đây là một sự cải tiến so với Android Views, trong đó bạn cần tránh các bố cục lớp lồng ghép vì lý do hiệu suất

Để đặt vị trí bố cục con trong Row, hãy đặt các đối số horizontalArrangement và verticalAlignment Đối với Column, hãy đặt các đối số verticalArrangement và horizontalAlignment:

Trang 27

5.4 Mô hình bố cục

Trong mô hình bố cục, cây giao diện người dùng được sắp xếp chỉ trong một luồng Trước tiên, mỗi nút được yêu cầu tự đo lường, sau đó đo lường định kỳ bất cứ thành phần con cháu nào, chuyển các giới hạn kích thước xuống dọc theo cây cho các thành phần con cháu Sau đó, cần định kích thước và đặt các nút lá, rồi các kích cỡ đã được xác định cùng các câu lệnh hướng dẫn vị trí được chuyển trở lại cây

Tóm lại, cần đo lường các thành phần mẹ trước các thành phần con cháu, nhưng việc định kích thước và đặt các thành phần mẹ lại diễn ra sau các thành phần con cháu

Hãy xem xét hàm SearchResult sau

Trang 28

Hàm này tạo cây giao diện người dùng sau đây

Trong ví dụ SearchResult, bố cục cây giao diện người dùng tuân theo thứ tự

sau:

1 Câu lệnh yêu cầu đo lường nút gốc Row

2 Nút gốc Row yêu cầu nút con cháu đầu tiên của nó, Image, đo lường 3 Image là một nút lá (nút không có nút con cháu), vì vậy nút này báo cáo

kích thước và trả về các câu lệnh hướng dẫn vị trí

4 Nút gốc Row yêu cầu nút con cháu thứ hai của nó, Column, đo lường 5 Nút Column yêu cầu nút con cháu đầu tiên của nó, Text, đo lường

6 Nút Text đầu tiên là một nút lá Nút lá chỉ báo cáo kích thước và trả về

câu lệnh hướng dẫn vị trí

7 Nút Column yêu cầu nút con cháu Text thứ hai của nó đo lường

8 Nút Text thứ hai là một nút lá, vì vậy nút này báo cáo kích thước và trả về

câu lệnh hướng dẫn vị trí

9 Hiện tại, nút Column đã đo lường xong, đã định kích thước và đặt các nút

con cháu của nó, nút này có thể xác định kích thước và vị trí của riêng mình

10 Hiện tại, nút gốc Row đã đo lường xong, đã định kích thước và đặt các

nút con cháu của nó, nút này có thể xác định kích thước và vị trí của riêng mình

Trang 29

5.5 Hiệu suất

Compose đạt được hiệu suất cao bằng cách đo lường nút con cháu một lần duy nhất Chế độ đo lường một luồng tốt cho hiệu suất, cho phép công cụ Compose xử lý sâu các cây giao diện người dùng một cách hiệu quả Nếu một thành phần đo lường thành phần con cháu của nó hai lần và thành phần con cháu đó đo lường từng thành phần con cháu của nó hai lần và cứ tiếp tục như vậy, thì một lần thử duy nhất để tạo ra toàn bộ Giao diện người dùng sẽ phải thực hiện rất nhiều việc, khiến ứng dụng của bạn khó duy trì hoạt động

Nếu bố cục của bạn cần nhiều lần đo lường vì một lý do nào đó, Compose có một hệ thống đặc biệt, phép đo lường hàm nội tại

Vì việc đo lường và vị trí là các giai đoạn phụ riêng biệt của luồng bố cục, nên các thay đổi chỉ ảnh hưởng đến vị trí của các mục mà không ảnh hưởng đến hoạt động đo lường, đều có thể được thực hiện riêng biệt

5.6 Sử dụng modifiers

Như đã đề cập ở phần các đối tượng sửa đổi trong Compose, bạn có thể sử dụng đối tượng sửa đổi để trang trí hoặc bổ sung các thành phần kết hợp của bạn Các đối tượng sửa đổi là thành phần cần thiết để tuỳ chỉnh bố cục của bạn Ví dụ: ở

đây chúng tôi liên kết một số đối tượng sửa đổi để tuỳ chỉnh ArtistCard:

Trang 30

Trong mã trên, hãy chú ý đến các đối tượng sửa đổi có chức năng khác nhau được sử dụng cùng nhau

• clickable tạo một phản ứng kết hợp với thông tin do người dùng nhập và

hiển thị một hiệu ứng gợn sóng

• padding đặt khoảng trống quanh một thành phần

• fillMaxWidth làm cho thành phần kết hợp lấp đầy chiều rộng tối đa mà

thành phần mẹ đã cấp cho nó

• size() xác định chiều rộng và chiều cao ưu tiên của một thành phần

Lưu ý: Cùng với một số nội dung khác, đối tượng sửa đổi đóng vai trò tương

tự như vai trò của các thông số bố cục trong bố cục chế độ xem Tuy nhiên, vì đối tượng sửa đổi đôi khi theo phạm vi cụ thể, nên chúng cung cấp sự an toàn về loại cũng như giúp bạn khám phá và tìm hiểu nội dung có sẵn và phù hợp với một bố cục nhất định Với bố cục XML, đôi khi khó để biết liệu một thuộc tính bố cục cụ thể có áp dụng cho một chế độ xem nhất định hay không

Ngoài ra còn có các loại bố cục đặc biệt khác như Scrollable Layout, Reponsive Layout, Slot-base Layout không được đề cập trong tài liệu này

6 Quản lý trạng thái

Trang 31

Trạng thái trong ứng dụng là giá trị bất kỳ có thể thay đổi theo thời gian Đây

là định nghĩa rất rộng và bao gồm mọi thứ từ cơ sở dữ liệu Room cho đến một biến

• Một bài đăng trên blog và các bình luận liên quan

• Ảnh động gợn sóng trên các nút phát khi người dùng nhấp vào • Hình dán mà người dùng có thể vẽ lên hình ảnh

Jetpack Compose giúp bạn hiểu rõ vị trí và cách thức lưu trữ cũng như dùng trạng thái trong một ứng dụng Android Tài liệu hướng dẫn này tập trung vào hoạt động kết nối giữa các trạng thái và thành phần kết hợp (composable), đồng thời tập trung vào những API mà Jetpack Compose cung cấp để xử lý trạng thái dễ dàng hơn

6.1 Trạng thái và composition

Compose mang tính khai báo và vì vậy, cách duy nhất để cập nhật Compose là gọi cùng một thành phần kết hợp (composable) với đối số mới Các đối số này là đại diện cho trạng thái giao diện người dùng Mỗi khi một trạng thái được cập nhật, một lượt tái cấu trúc (recomposition) diễn ra Do đó, những thành phần như TextField sẽ không tự động cập nhật như đối với khung hiển thị dựa trên XML bắt buộc Một thành phần kết hợp phải được thông báo rõ ràng về trạng thái mới để cập nhật tương ứng

Trang 32

Nếu thực hiện việc này, bạn sẽ thấy rằng không có điều gì xảy ra Nguyên nhân là do TextField không tự cập nhật, mà sẽ cập nhật khi tham số value của nó thay đổi Lý do nằm ở cách hoạt động của tính năng cấu trúc (composition) và tái cấu trúc (recomposition) trong Compose

6.2 Trạng thái trong composition

Các hàm có khả năng kết hợp có thể sử dụng API remember để lưu trữ đối tượng trong bộ nhớ Một giá trị do remember tính toán được lưu trữ trong Cấu trúc (Composition) trong quá trình cấu trúc ban đầu Giá trị đã lưu trữ được trả về trong quá trình tái cấu trúc Bạn có thể dùng remember để lưu trữ cả đối tượng có thể thay đổi và không thể thay đổi

mutableStateOf tạo ra MutableState<T> có thể quan sát Đây là một loại đối

tượng có thể quan sát được tích hợp với thời gian chạy Compose

Mọi thay đổi đối với value sẽ lên lịch tái cấu trúc mọi hàm có khả năng kết hợp có thể đọc value Trong trường hợp ExpandingCard, bất cứ khi nào expanded thay đổi, hệ thống sẽ tái cấu trúc ExpandingCard

Có 3 cách để khai báo đối tượng MutableState trong một thành phần kết hợp:

• val mutableState = remember { mutableStateOf(default) } • var value by remember { mutableStateOf(default) }

Trang 33

• val (value, setValue) = remember { mutableStateOf(default) }

Các thông tin khai báo này là tương đương và được cung cấp dưới dạng cú pháp dễ hiểu theo mục đích sử dụng của trạng thái Bạn nên chọn định dạng tạo ra mã dễ đọc nhất trong thành phần kết hợp mà bạn đang viết

Cú pháp uỷ quyền (delegate syntax) by yêu cầu các import sau:

Bạn có thể sử dụng giá trị đã ghi nhớ làm tham số cho các thành phần kết hợp khác hoặc thậm chí là logic trong các câu lệnh để thay đổi thành phần kết hợp được hiển thị Ví dụ: nếu bạn không muốn hiện lời chào nếu phần tên trống, hãy sử dụng

trạng thái trong câu lệnh if:

Mặc dù remember giúp bạn giữ lại trạng thái trên các lần tái cấu trúc, trạng

thái này sẽ không được giữ lại khi bạn thay đổi cấu hình Để làm được điều này,

Trang 34

nó trở thành không trạng thái Mô hình chung để di chuyển trạng thái lên trên trong Jetpack Compose là thay thế biến trạng thái bằng 2 tham số:

• value: T: giá trị hiện tại để hiển thị

• onValueChange: (T) -> Unit: một sự kiện yêu cầu thay đổi giá trị này, trong đó T là giá trị mới được đề xuất

Tuy nhiên, bạn không bị giới hạn ở onValueChange Nếu các sự kiện cụ thể

hơn phù hợp với thành phần kết hợp, bạn nên xác định sự kiện bằng cách sử dụng

lambda như ExpandingCard với onExpand và onCollapse

Trạng thái được di chuyển lên trên theo cách này có một số thuộc tính quan trọng:

• Một nguồn đáng tin cậy (single source of truth): Bằng cách di chuyển trạng thái thay vì sao chép, chúng tôi đảm bảo rằng chỉ có một nguồn thông tin duy nhất Điều này giúp tránh các lỗi

• Được đóng gói (encapsulated): Chỉ các thành phần kết hợp có trạng thái mới có thể sửa đổi trạng thái của chúng Nó có tính nội bộ hoàn toàn • Có thể chia sẻ (shareable): Bạn có thể chia sẻ trạng thái được di chuyển

lên trên với nhiều thành phần kết hợp Nếu bạn muốn đọc name trong

một thành phần kết hợp khác, việc di chuyển trạng thái lên trên sẽ cho phép bạn làm việc đó

• Có thể chắn (interceptable): phương thức gọi đến các thành phần kết hợp không trạng thái có thể quyết định bỏ qua hoặc sửa đổi các sự kiện trước khi thay đổi trạng thái

• Được tách riêng (decoupled): trạng thái của ExpandingCard không có

trạng thái có thể được lưu trữ ở bất cứ đâu Ví dụ: bạn hiện có thể di

chuyển name sang ViewModel

Trong trường hợp ví dụ, bạn trích xuất name và onValueChange ra HelloContent rồi di chuyển chúng lên trên đến một thành phần kết hợp HelloScreen bằng lệnh gọi HelloContent

Trang 35

Bằng cách nâng trạng thái ra khỏi HelloContent, sẽ dễ dàng cho việc lý giải thành phần kết hợp, tái sử dụng trong nhiều tình huống và kiểm thử HelloContent

được tách riêng khỏi cách lưu trữ trạng thái của tệp Việc tách riêng có nghĩa là nếu

sửa đổi hoặc thay thế HelloScreen, bạn không phải thay đổi cách thức triển khai HelloContent

Trang 36

Mô hình mà trạng thái giảm và các sự kiện tăng lên được gọi là luồng dữ liệu một chiều (unidirectional) Trong trường hợp này, trạng thái giảm từ HelloScreen

xuống HelloContent và các sự kiện tăng từ HelloContent lên HelloScreen Bằng

cách làm theo luồng dữ liệu một chiều, bạn có thể phân tách các thành phần có thể kết hợp hiển thị trạng thái trong giao diện người dùng khỏi các phần của ứng dụng lưu trữ và thay đổi trạng thái

Lưu ý quan trọng: Khi chuyển trạng thái lên trên, có ba quy tắc giúp bạn tìm ra vị trí di chuyển trạng thái:

1 Trạng thái phải được di chuyển lên ít nhất đến trạng thái mẹ phổ biến thấp nhất trong tất cả thành phần kết hợp đang sử dụng trạng thái (đọc) 2 Trạng thái phải được di chuyển lên ít nhất đến cấp cao nhất mà nó có

thể được thay đổi (ghi)

3 Nếu 2 trạng thái thay đổi để phản hồi cùng một sự kiện, thì chúng phải được di chuyển lên trên cùng nhau

Bạn có thể chuyển trạng thái lên cao hơn so với yêu cầu trong các quy tắc này, nhưng trạng thái được chuyển lên trên không đúng mức sẽ làm cho việc đi theo luồng dữ liệu một chiều trở nên khó khăn hoặc bất khả thi

6.4 Khôi phục trạng thái

Sử dụng rememberSaveable để khôi phục trạng thái trên giao diện người dùng sau khi tái tạo một hoạt động hoặc quy trình rememberSaveable giữ lại trạng thái trên các quá trình tái cấu trúc Ngoài ra, rememberSaveable còn giữ nguyên trạng

thái trên quá trình tái tạo một hoạt động hoặc quy trình

Tất cả loại dữ liệu được thêm vào Bundle sẽ được lưu tự động Nếu muốn lưu nội dung nào đó mà không thể thêm vào Bundle, bạn có thể làm theo các cách sau:

Trang 37

6.4.2 MapSaver

Nếu vì lý do nào đó @Parcelize không phù hợp, bạn có thể sử dụng mapSaver để xác định quy tắc của riêng mình nhằm chuyển đổi một đối tượng thành một tập hợp giá trị mà hệ thống có thể lưu vào Bundle

6.5 Phần tử giữ trạng thái

Có thể quản lý quá trình chuyển trạng thái lên trên đơn giản trong chính các hàm có khả năng kết hợp Tuy nhiên, nếu số lượng trạng thái cần theo dõi tăng lên

Trang 38

Ở đây, việc sử dụng hàm remember giúp giá trị MutableState vẫn tiếp tục có

hiệu lực khi kết hợp lại

Nói chung, remember nhận tham số lambda calculation Trong lần chạy đầu

tiên, remember sẽ gọi hàm lambda calculation và lưu trữ kết quả Trong quá trình

kết hợp lại, remember sẽ trả về giá trị được lưu trữ gần đây nhất

Ngoài trạng thái lưu vào bộ nhớ đệm, bạn cũng có thể sử dụng remember để

lưu trữ đối tượng bất kỳ hoặc kết quả của một thao tác trong Cấu trúc (Composition) nếu tốn kém khi khởi chạy hoặc tính toán Bạn có thể không muốn lặp lại phép tính này trong mỗi quá trình kết hợp lại Ví dụ như việc tạo đối tượng

ShaderBrush này có thể là một thao tác tốn kém:

remember lưu trữ giá trị cho đến khi thoát khỏi Cấu trúc Tuy nhiên, có một cách để vô hiệu hoá giá trị đã lưu vào bộ nhớ đệm API remember cũng lấy tham số

key hoặc keys Nếu bất kỳ khoá nào trong số này thay đổi thì lần tiếp theo khi hàm

kết hợp lại, remember sẽ vô hiệu hoá bộ nhớ đệm và thực thi lại khối lambda tính

toán Cơ chế này cho phép bạn kiểm soát toàn thời gian của một đối tượng trong Cấu trúc Phương pháp tính toán này vẫn có hiệu lực cho đến khi giá trị nhập thay đổi, thay vì cho đến khi giá trị được ghi nhớ bị xoá khỏi Cấu trúc

Các ví dụ sau đây minh hoạ cách hoạt động của cơ chế này

Trong đoạn mã này, ShaderBrush được tạo và sử dụng làm màu nền của thành phần kết hợp Box remember lưu trữ thực thể ShaderBrush vì việc tạo lại rất tốn kém, như chúng tôi đã giải thích trước đó remember lấy avatarRes làm tham số key1, là hình nền đã chọn Nếu avatarRes thay đổi, bút vẽ sẽ kết hợp lại với hình

Trang 39

ảnh mới và áp dụng lại cho Box Điều này có thể xảy ra khi người dùng chọn một

hình ảnh khác trong bộ chọn làm hình nền

Trong đoạn mã tiếp theo, trạng thái được chuyển lên trên lớp phần tử giữ trạng

thái thuần tuý MyAppState Phương thức này hiển thị một hàm rememberMyAppState để khởi chạy một phiên bản của lớp bằng cách dùng remember Việc hiển thị các hàm như vậy để tạo phiên bản tiếp tục có hiệu lực

trong quá trình kết hợp lại là một mẫu phổ biến trong Compose Hàm

rememberMyAppState nhận windowSizeClass, đóng vai trò là tham số key cho remember Nếu tham số này thay đổi, ứng dụng cần tạo lại phần tử giữ trạng thái

thuần tuý có giá trị mới nhất Điều này có thể xảy ra nếu người dùng xoay thiết bị chẳng hạn

Compose sử dụng cách triển khai tương đương của lớp để quyết định xem một

Trang 40

hợp Một thành phần Compose là cấu trúc dạng cây của các thành phần kết hợp mô tả Giao diện người dùng

Khi Jetpack Compose chạy các thành phần kết hợp lần đầu tiên, trong quá trình kết hợp ban đầu, bộ công cụ này sẽ theo dõi các thành phần kết hợp bạn gọi để mô tả Giao diện người dùng trong một thành phần Compose Sau đó, khi trạng thái ứng dụng thay đổi, Jetpack Compose sẽ lên lịch kết hợp lại Quá trình kết hợp lại xảy ra khi Jetpack Compose tái thực thi các thành phần kết hợp có thể thay đổi theo thay đổi về trạng thái, tiếp đến cập nhật thành phần Compose để phản ánh mọi thay đổi

Thành phần Compose chỉ có thể được quá trình kết hợp ban đầu tạo ra và cập nhật bằng quá trình kết hợp lại Phương pháp duy nhất để chỉnh sửa thành phần Compose là kết hợp lại

Hình 1 Vòng đời của một thành phần kết hợp trong thành phần Compose

Thành phần kết hợp này sẽ được nhập vào thành phần Compose, kết hợp lại từ 0 lần trở lên, cuối cùng ra khỏi thành phần Compose

Quá trình kết hợp lại thường được kích hoạt khi có thay đổi đối với đối tượng

State<T> Compose sẽ theo dõi quá trình thay đổi này, đồng thời chạy tất cả thành phần kết hợp trong thành phần Compose có khả năng đọc State<T> và bất kỳ thành

phần kết hợp quá trình này gọi mà không thể bỏ qua

Ngày đăng: 15/05/2024, 09:29

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan