Bối cảnh và vấn đề nghiên cứu

Trong lĩnh vực phát triển ứng dụng di động, các nền tảng đa nền tảng (cross-platform) như Flutter hay React Native giúp tối ưu hóa thời gian và chi phí phát triển. Tuy nhiên, các tổ chức công nghệ quy mô lớn vẫn ưu tiên ứng dụng bản địa (native) nhằm tối ưu hiệu năng vận hành và bảo đảm trải nghiệm người dùng liền mạch. Mặc dù vậy, phương pháp phát triển ứng dụng Android native truyền thống tồn tại rào cản kỹ thuật lớn: lập trình viên buộc phải sử dụng song song hai ngôn ngữ khác nhau gồm ngôn ngữ logic (Java hoặc Kotlin) và ngôn ngữ định dạng giao diện (XML). Quy trình này làm gia tăng thời gian học tập, gây phân mảnh mã nguồn và gia tăng chi phí bảo trì hệ thống.

Từ sau sự kiện Google I/O 2019, Kotlin đã trở thành ngôn ngữ ưu tiên hàng đầu cho Android. Sự ra đời của Jetpack Compose – bộ công cụ xây dựng giao diện người dùng khai báo hoàn toàn bằng ngôn ngữ Kotlin – đã giải quyết triệt để sự phân tách giữa logic và giao diện, cho phép toàn bộ mã nguồn ứng dụng được viết thống nhất bằng một ngôn ngữ duy nhất.

Đồ án "Xây dựng ứng dụng chia sẻ công thức món ăn" do sinh viên Bùi Lê Hoài An (MSSV: 20520985, lớp SE122.O11) thực hiện dưới sự hướng dẫn của ThS. Huỳnh Tuấn Anh tại Khoa Công nghệ Phần mềm, Trường Đại học Công nghệ Thông tin – Đại học Quốc gia TP.HCM (tháng 12/2023) tập trung vào các mục tiêu và nhiệm vụ nghiên cứu sau:

  1. Nghiên cứu tổng quan và chuyên sâu về mô hình tư duy, cách thức hoạt động, các ưu - khuyết điểm và hệ sinh thái thư viện, package đi kèm Jetpack Compose.
  2. Tìm hiểu cơ chế lưu trữ dữ liệu, quản lý trạng thái và tối ưu hóa chu trình kết hợp lại (recomposition) trong ứng dụng di động.
  3. Tìm hiểu định hướng ứng dụng học máy trên thiết bị di động (TensorFlow Lite) kết hợp trong ứng dụng di động.
  4. Hiện thực hóa các nội dung lý thuyết thông qua việc phân tích, thiết kế và xây dựng ứng dụng thực tế mang tên "Recipely – Just a simple recipe app".

Phạm vi nghiên cứu của đề tài giới hạn trong hệ sinh thái Android native, tập trung vào bộ công cụ Jetpack Compose và quy trình phát triển ứng dụng di động tại Khoa Công nghệ Phần mềm trong mốc thời gian hoàn thành vào tháng 12 năm 2023.


Cơ sở lý thuyết và phương pháp

Đồ án xây dựng nền tảng dựa trên các khung lý thuyết, công nghệ và phương pháp kỹ thuật phần mềm chuẩn mực:

Thành phần Chi tiết công nghệ / Lý thuyết áp dụng Mục đích trong đề tài
Ngôn ngữ lập trình Kotlin (JetBrains / Google) Hỗ trợ hướng đối tượng (OOP), lập trình hàm (FP), tính năng null safety, extension function và tương thích hoàn toàn với JVM/Java.
Bộ công cụ UI Jetpack Compose (Google) Xây dựng giao diện người dùng theo mô hình lập trình khai báo (Declarative UI) dựa trên hàm @Composable.
Quản lý trạng thái Unidirectional Data Flow (UDF), State Hoisting, remember, rememberSaveable, MutableState Tách biệt trạng thái khỏi thành phần giao diện, duy trì trạng thái qua chu kỳ cấu hình lại.
Kiến trúc hệ thống Multi-module Architecture, Android Architecture Components (ViewModel, LiveData, Room) Giải quyết vấn đề độ phình mã nguồn, tăng tính mô-đun hóa, dễ tái sử dụng và kiểm thử.
Trí tuệ nhân tạo TensorFlow Lite Định hướng tích hợp mô hình học máy (Machine Learning) trực tiếp trên thiết bị di động.
Công cụ phát triển Android Studio, Google Colab, GitHub Lập trình giao diện/hệ thống, huấn luyện mô hình và quản lý phiên bản mã nguồn.

Phương pháp nghiên cứu chính được triển khai là phương pháp nghiên cứu thực nghiệm và thiết kế - phát triển kỹ thuật phần mềm (Design and Implementation):

  • Phân tích và tổng hợp lý thuyết: Hệ thống hóa các nguyên lý lập trình khai báo, vòng đời Composable, cơ chế kết hợp lại (recomposition), đo lường bố cục đơn luồng và ba giai đoạn kết xuất khung hình.
  • Phương pháp mô hình hóa phần mềm: Phân tích yêu cầu chức năng, phi chức năng, ràng buộc logic, thiết lập lược đồ Use-Case và thiết kế luồng chuyển dịch màn hình (Screen Flow).
  • Phương pháp thiết kế kiến trúc: Áp dụng kiến trúc đa mô-đun (Multi-module) kết hợp các mẫu thiết kế hướng trạng thái.

Nội dung chính theo từng chương

Chương 1: Giới thiệu tổng quan

Chương 1 thiết lập các thông tin cơ sở của đồ án bao gồm thông tin tác giả, giảng viên hướng dẫn và tổng quan đề tài. Tác giả phân tích sự đối sánh giữa các giải pháp đa nền tảng và phát triển bản địa, chỉ ra điểm nghẽn của việc sử dụng song song Java/Kotlin và XML. Nội dung nghiên cứu được xác định rõ là khảo sát cơ chế vận hành của Jetpack Compose và áp dụng xây dựng ứng dụng thực tế. Hai kết quả hướng tới là nâng cao năng lực làm chủ framework mới và tiếp cận việc tích hợp Machine Learning vào môi trường di động. Danh mục công cụ phục vụ nghiên cứu gồm Android Studio (giao diện và logic), Google Colab (huấn luyện mô hình) và GitHub (quản lý mã nguồn).

Chương 2: Công nghệ sử dụng

Chương 2 trình bày chi tiết về nền tảng lý thuyết kỹ thuật của Kotlin và Jetpack Compose:

  • Đặc trưng Kotlin: Khả năng kết hợp OOP và FP, cú pháp ngắn gọn, an toàn với con trỏ null, extension functions và tính tương thích Java.
  • Mô hình tư duy Jetpack Compose: Chuyển đổi từ mô hình mệnh lệnh truyền thống (nơi hệ phân cấp View được cập nhật thủ công qua findViewById(), setter/getter dễ dẫn đến xung đột trạng thái) sang mô hình khai báo (tái tạo màn hình thông qua các hàm @Composable nhận dữ liệu đầu vào và phát sinh giao diện).
  • Quy tắc của hàm Composable: Phải được đánh dấu chú thích @Composable, không trả về giá trị (Unit), chạy nhanh, có tính idempotent (bất biến) và không chứa tác dụng phụ (side-effects).
  • Cơ chế Recomposition: Giải thích nguyên lý Recomposition thông minh — chỉ vẽ lại các nút có dữ liệu thay đổi; có thể thực thi theo thứ tự bất kỳ, chạy song song trên nhiều luồng nền, có thể bị hủy nếu dữ liệu đầu vào thay đổi giữa chừng (tính khả quan) và bỏ qua việc thực thi lại đối với các kiểu dữ liệu ổn định (Stable Types).
  • Hệ thống bố cục và Modifier: Giới thiệu các bố cục nền tảng gồm Column, Row, Box cùng các thuộc tính căn chỉnh (horizontalArrangement, verticalAlignment). Cơ chế đo lường bố cục đơn luồng (Single-pass measurement) giúp tối ưu hiệu năng và xử lý tốt các cấu trúc lồng nhau mà không bị suy giảm tốc độ như hệ thống Android View cũ. Các đối tượng sửa đổi (Modifier) như clickable, padding, fillMaxWidth, size cung cấp khả năng trang trí và an toàn kiểu dữ liệu.
  • Quản lý trạng thái và luồng dữ liệu một chiều (UDF): Khái niệm trạng thái trong Composition; các API remember và mutableStateOf; kỹ thuật chuyển trạng thái lên trên (State Hoisting) để tạo các hàm không trạng thái (stateless); khôi phục trạng thái bằng rememberSaveable, @Parcelize, mapSaver; sử dụng các phần tử giữ trạng thái (State Holders) và tái kích hoạt tính toán qua key.
  • Vòng đời Composable và ba giai đoạn của một frame: Vòng đời gồm: đi vào Composition, tái kết hợp từ 0 đến nhiều lần, và rời khỏi Composition. Xác định thực thể Composable dựa trên vị trí gọi (call-site) và khóa (key). Ba giai đoạn kết xuất một frame gồm: Composition (Sáng tác nội dung) -> Layout (Đo lường và Đặt vị trí) -> Drawing (Vẽ lên Canvas). Quá trình đọc trạng thái theo từng giai đoạn giúp giảm thiểu tối đa khối lượng công việc kết xuất lại.
  • TensorFlow Lite cho thiết bị di động: Đặt nền móng kỹ thuật cho việc nhúng các mô hình trí tuệ nhân tạo gọn nhẹ trên nền tảng Android.

Chương 3: Xây dựng ứng dụng

Chương 3 mô tả quá trình hiện thực hóa ứng dụng "Recipely – Just a simple recipe app":

  • Tổng quan ứng dụng: Trình bày lý do xây dựng ứng dụng, đối tượng người dùng hướng đến, môi trường phát triển và kết quả mong đợi.
  • Quy trình triển khai: Khái quát các giai đoạn từ thu thập yêu cầu, phân tích thiết kế đến hiện thực mã nguồn.
  • Phân tích yêu cầu phần mềm: Xác định các yêu cầu chức năng cốt lõi (chia sẻ, tra cứu công thức món ăn), các ràng buộc logic ban đầu, tiêu chí về tính khả dụng và xây dựng lược đồ Use-Case hệ thống.
  • Thiết kế hệ thống:
    • Kiến trúc đa mô-đun (Multi-module architecture): Phân tách mã nguồn thành các mô-đun độc lập nhằm kiểm soát độ phức tạp khi dự án mở rộng, tối ưu thời gian biên dịch và bảo đảm tính độc lập giữa các tầng nghiệp vụ.
    • Kiến trúc ứng dụng: Định hình luồng dữ liệu theo kiến trúc chuẩn của Android, phân định rõ ràng giữa tầng hiển thị (UI Layer) và tầng dữ liệu (Data Layer).
  • Thiết kế dữ liệu và giao diện: Thiết kế cấu trúc lưu trữ dữ liệu, sơ đồ liên kết giữa các màn hình (Screen flow) và chi tiết danh sách các màn hình giao diện người dùng.
  • Cài đặt và thử nghiệm: Triển khai các màn hình bằng Jetpack Compose và kiểm thử chức năng vận hành thực tế.

Chương 4: Kết luận

Chương 4 đúc kết các kết quả đạt được của đề tài, đánh giá mức độ hoàn thành so với mục tiêu ban đầu về việc làm chủ Jetpack Compose và xây dựng thành công ứng dụng Recipely. Đồng thời, tác giả vạch ra các hướng phát triển tiếp theo của sản phẩm trong tương lai.


Thiết kế và triển khai

Hệ thống của đồ án được triển khai xoay quanh các giải pháp kỹ thuật cụ thể:

1. Kiến trúc hệ thống và đa mô-đun (Multi-module Architecture)

Nhằm khắc phục vấn đề độ lớn của mã nguồn (code size/bloat) trong các dự án di động phức tạp, tác giả áp dụng kiến trúc Multi-module. Cấu trúc này chia nhỏ hệ thống thành các module chuyên biệt:

  • Phân tách module theo tính năng (feature modules) và module lõi/chia sẻ (core/common modules).
  • Giảm thiểu sự phụ thuộc vòng, cho phép tái sử dụng mã nguồn và cải thiện hiệu suất biên dịch gia tăng (incremental build) trong Android Studio.
  • Tầng giao diện tuân thủ mô hình UDF: dữ liệu trạng thái đi xuống (state flows down) từ ViewModel tới các Composable, trong khi các sự kiện người dùng đi lên (events flow up) thông qua các biểu thức lambda callback.

2. Quản lý trạng thái và tối ưu hóa luồng dựng hình

Ứng dụng áp dụng triệt để kỹ thuật chuyển trạng thái lên trên (State Hoisting) theo 3 quy tắc được xác lập trong đồ án:

  1. Trạng thái phải được chuyển lên ít nhất đến cấp nút cha chung thấp nhất của tất cả các Composable đọc trạng thái đó.
  2. Trạng thái phải được chuyển lên ít nhất đến cấp cao nhất mà nó có thể bị thay đổi.
  3. Nếu hai trạng thái cùng thay đổi để phản hồi một sự kiện, chúng phải được chuyển lên cùng nhau.

Để đảm bảo hiệu năng và tránh hiện tượng giật khung hình (jank), các tác vụ nặng (như truy xuất dữ liệu, tính toán phức tạp) được tách khỏi hàm Composable và thực thi trên coroutine nền. Cơ chế theo dõi đọc trạng thái theo từng giai đoạn (Composition, Layout, Drawing) giúp hệ thống chỉ kích hoạt lại giai đoạn tối thiểu cần thiết thay vì vẽ lại toàn bộ giao diện.

3. Quy trình công nghệ và công cụ

Toàn bộ mã nguồn giao diện được xây dựng bằng ngôn ngữ Kotlin trên môi trường Android Studio. Việc huấn luyện mô hình học máy được thực hiện thông qua Google Colab trước khi chuyển đổi sang định dạng TensorFlow Lite để tích hợp vào ứng dụng. Mã nguồn được kiểm soát phiên bản và cộng tác qua GitHub.


Kết quả và đóng góp

  1. Về mặt kỹ thuật phần mềm: Đồ án tổng hợp và chuẩn hóa toàn bộ lý thuyết nền tảng về Jetpack Compose, từ mô hình lập trình khai báo, cơ chế recomposition thông minh, đo lường bố cục đơn luồng đến quy tắc quản lý trạng thái nâng cao và ba giai đoạn của một frame.
  2. Về mặt ứng dụng thực tiễn: Xây dựng hoàn chỉnh ứng dụng di động bản địa "Recipely – Just a simple recipe app" đáp ứng đầy đủ quy trình từ thu thập yêu cầu, mô hình hóa Use-case, thiết kế kiến trúc đa mô-đun (Multi-module) đến thiết kế dữ liệu và hệ thống màn hình UI trực quan.
  3. Về mặt phương pháp luận: Minh chứng tính khả thi và hiệu quả vượt trội của việc chuyển đổi hoàn toàn sang 100% mã nguồn Kotlin trong phát triển ứng dụng Android native, loại bỏ sự phụ thuộc vào tệp bố cục XML truyền thống mà vẫn bảo đảm tối ưu hóa hiệu năng render.

Hạn chế và hướng nghiên cứu tiếp

  • Hạn chế: Theo phạm vi nghiên cứu được tác giả xác định trong tài liệu, một số loại bố cục chuyên biệt nâng cao trong Compose như bố cục có thể cuộn phức tạp (Scrollable Layout), bố cục phản hồi đa kích thước màn hình (Responsive Layout) và bố cục dạng khe cắm nâng cao (Slot-based Layout) chưa được phân tích toàn diện.
  • Hướng phát triển tiếp theo:
    • Hoàn thiện và mở rộng các tính năng nghiệp vụ cho ứng dụng Recipely.
    • Tích hợp sâu hơn mô hình trí tuệ nhân tạo TensorFlow Lite để nhận diện hình ảnh món ăn hoặc gợi ý công thức thông minh trực tiếp trên thiết bị di động.
    • Mở rộng nghiên cứu các mẫu kiến trúc và tối ưu hóa hiệu năng nâng cao cho các màn hình có dữ liệu lớn.

Giá trị tham khảo

Tài liệu này là tài liệu tham khảo giá trị cho:

  • Sinh viên ngành Kỹ thuật Phần mềm và Công nghệ Thông tin: Đặc biệt là những người đang thực hiện đồ án chuyên ngành, đồ án tốt nghiệp liên quan đến phát triển ứng dụng di động Android native.
  • Lập trình viên Android: Những người đang trong quá trình chuyển đổi từ phương pháp xây dựng giao diện XML/View truyền thống sang Jetpack Compose, cần nắm vững mô hình tư duy khai báo, vòng đời Composable và cơ chế quản lý trạng thái luồng dữ liệu một chiều (UDF).
  • Kỹ sư thiết kế kiến trúc phần mềm di động: Tham khảo phương án triển khai kiến trúc đa mô-đun (Multi-module architecture) nhằm giải quyết bài toán quy mô mã nguồn trong các ứng dụng thực tế.

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

1. Tại sao tác giả đề xuất sử dụng Jetpack Compose thay thế cho hệ thống Android View/XML truyền thống?

Trong phương pháp truyền thống, lập trình viên phải duy trì song song hai ngôn ngữ: Java/Kotlin cho logic và XML cho giao diện, dẫn đến tốn thời gian và tăng chi phí bảo trì. Jetpack Compose hợp nhất toàn bộ mã nguồn về duy nhất ngôn ngữ Kotlin theo mô hình khai báo, giúp mã nguồn ngắn gọn, dễ đọc, hỗ trợ tái sử dụng cao và tối ưu hóa hiệu năng thông qua cơ chế Recomposition thông minh.

2. Quá trình kết hợp lại (Recomposition) trong Jetpack Compose hoạt động theo nguyên lý nào?

Recomposition là quá trình gọi lại các hàm Composable khi tham số đầu vào của chúng thay đổi. Compose tối ưu hóa bằng cách chỉ thực thi lại những hàm hoặc khối lambda có dữ liệu bị thay đổi và bỏ qua các thành phần còn lại. Recomposition có thể chạy song song trên nhiều luồng, thực thi theo thứ tự bất kỳ và có tính khả quan (có thể bị hủy bỏ và khởi động lại nếu tham số tiếp tục thay đổi trước khi hoàn tất). Do đó, các hàm Composable bắt buộc phải không có tác dụng phụ (side-effect free).

3. Ba quy tắc cốt lõi khi thực hiện chuyển trạng thái lên trên (State Hoisting) là gì?

Theo đồ án, 3 quy tắc định vị trạng thái gồm:

  1. Trạng thái phải được chuyển lên ít nhất đến cấp cha chung thấp nhất của tất cả các Composable có đọc trạng thái đó.
  2. Trạng thái phải được chuyển lên ít nhất đến cấp cao nhất mà tại đó trạng thái có thể bị thay đổi.
  3. Nếu hai trạng thái cùng thay đổi để phản hồi cùng một sự kiện, chúng phải được chuyển lên trên cùng nhau.

4. Ba giai đoạn hiển thị một khung hình (frame) trong Jetpack Compose diễn ra như thế nào?

Một frame trong Compose trải qua 3 giai đoạn theo luồng dữ liệu một chiều:

  1. Composition (Sáng tác): Xác định nội dung hiển thị bằng cách chạy các hàm Composable để mô tả cây giao diện.
  2. Layout (Bố cục): Xác định vị trí đặt giao diện qua hai bước: đo lường kích thước (measure) và đặt vị trí (place) theo tọa độ 2D.
  3. Drawing (Bản vẽ): Xác định cách thức hiển thị bằng cách vẽ các thành phần lên Canvas màn hình.

5. Ứng dụng "Recipely" giải quyết bài toán kiến trúc hệ thống như thế nào?

Để giải quyết vấn đề độ lớn mã nguồn và tính phức tạp khi mở rộng, tác giả thiết kế ứng dụng theo kiến trúc đa mô-đun (Multi-module architecture), phân tách độc lập các module chức năng và module dùng chung, kết hợp mô hình luồng dữ liệu một chiều (UDF) để đảm bảo tính đóng gói, dễ bảo trì và thuận tiện cho việc kiểm thử.


Kết luận

Báo cáo Đồ án 2 "Xây dựng ứng dụng chia sẻ công thức món ăn" của tác giả Bùi Lê Hoài An là một công trình nghiên cứu và thực nghiệm bài bản trong lĩnh vực phát triển ứng dụng di động Android bản địa. Đề tài đã hệ thống hóa sâu sắc các nguyên lý kỹ thuật của Jetpack Compose và hiện thực hóa thành công vào sản phẩm ứng dụng "Recipely" thông qua kiến trúc đa mô-đun chuẩn mực. Đây là nguồn tài liệu học thuật và kỹ thuật giá trị, cung cấp cái nhìn toàn diện về phương pháp lập trình giao diện khai báo hiện đại cho sinh viên và kỹ sư phần mềm.