Theo dõi thói quen google sheet

Hướng dẫn này bao gồm các phương pháp hay nhất và kiến ​​trúc được đề xuất để xây dựng các ứng dụng mạnh mẽ, chất lượng cao

Ghi chú. Trang này giả định rằng bạn đã quen thuộc cơ bản với Android Framework. Nếu bạn chưa quen với việc phát triển ứng dụng Android, hãy xem khóa học Cơ bản về Android để bắt đầu và tìm hiểu thêm về các khái niệm được đề cập trong hướng dẫn này

Trải nghiệm người dùng ứng dụng di động

Một ứng dụng Android điển hình chứa nhiều thành phần ứng dụng, bao gồm các hoạt động, phân đoạn, dịch vụ, nhà cung cấp nội dung và bộ thu quảng bá. Bạn khai báo hầu hết các thành phần ứng dụng này trong bảng kê khai ứng dụng của mình. Hệ điều hành Android sau đó sử dụng tệp này để quyết định cách tích hợp ứng dụng của bạn vào trải nghiệm người dùng tổng thể của thiết bị. Do một ứng dụng Android điển hình có thể chứa nhiều thành phần và người dùng thường tương tác với nhiều ứng dụng trong một khoảng thời gian ngắn, nên các ứng dụng cần phải thích ứng với các loại quy trình và tác vụ khác nhau do người dùng điều khiển

Hãy nhớ rằng các thiết bị di động cũng bị hạn chế về tài nguyên, vì vậy bất cứ lúc nào hệ điều hành cũng có thể tắt một số quy trình ứng dụng để nhường chỗ cho các quy trình mới.

Với các điều kiện của môi trường này, các thành phần ứng dụng của bạn có thể được khởi chạy riêng lẻ và không theo thứ tự, đồng thời hệ điều hành hoặc người dùng có thể hủy chúng bất kỳ lúc nào. Vì những sự kiện này không nằm dưới sự kiểm soát của bạn, nên bạn không nên lưu trữ hoặc giữ bất kỳ dữ liệu hoặc trạng thái ứng dụng nào trong bộ nhớ trong các thành phần ứng dụng của mình và các thành phần ứng dụng của bạn không nên phụ thuộc vào nhau

Nguyên tắc kiến ​​trúc chung

Nếu bạn không nên sử dụng các thành phần ứng dụng để lưu trữ dữ liệu và trạng thái của ứng dụng, thì thay vào đó, bạn nên thiết kế ứng dụng của mình như thế nào?

Khi các ứng dụng Android tăng kích thước, điều quan trọng là phải xác định một kiến ​​trúc cho phép ứng dụng mở rộng quy mô, tăng độ mạnh mẽ của ứng dụng và giúp ứng dụng dễ kiểm tra hơn

Kiến trúc ứng dụng xác định ranh giới giữa các phần của ứng dụng và trách nhiệm mà mỗi phần phải có. Để đáp ứng các nhu cầu nêu trên, bạn nên thiết kế kiến ​​trúc ứng dụng của mình tuân theo một số nguyên tắc cụ thể

Tách mối quan tâm

Nguyên tắc quan trọng nhất cần tuân theo là tách biệt các mối quan tâm. Đó là một sai lầm phổ biến khi viết tất cả mã của bạn trong một Activity hoặc một Fragment. Các lớp dựa trên giao diện người dùng này chỉ nên chứa logic xử lý các tương tác giữa giao diện người dùng và hệ điều hành. Bằng cách giữ cho các lớp này gọn gàng nhất có thể, bạn có thể tránh được nhiều vấn đề liên quan đến vòng đời của thành phần và cải thiện khả năng kiểm tra của các lớp này

Hãy nhớ rằng bạn không sở hữu việc triển khai ActivityFragment; . Hệ điều hành có thể hủy chúng bất cứ lúc nào dựa trên tương tác của người dùng hoặc do các điều kiện hệ thống như bộ nhớ thấp. Để cung cấp trải nghiệm người dùng hài lòng và trải nghiệm bảo trì ứng dụng dễ quản lý hơn, tốt nhất bạn nên giảm thiểu sự phụ thuộc của mình vào chúng

Lái xe giao diện người dùng từ các mô hình dữ liệu

Một nguyên tắc quan trọng khác là bạn nên điều khiển giao diện người dùng của mình từ các mô hình dữ liệu, tốt nhất là các mô hình liên tục. Mô hình dữ liệu đại diện cho dữ liệu của một ứng dụng. Chúng độc lập với các thành phần giao diện người dùng và các thành phần khác trong ứng dụng của bạn. Điều này có nghĩa là chúng không bị ràng buộc với vòng đời của thành phần ứng dụng và giao diện người dùng, nhưng vẫn sẽ bị hủy khi HĐH quyết định xóa quy trình của ứng dụng khỏi bộ nhớ

Các mô hình liên tục là lý tưởng vì những lý do sau

  • Người dùng của bạn không bị mất dữ liệu nếu hệ điều hành Android hủy ứng dụng của bạn để giải phóng tài nguyên

  • Ứng dụng của bạn tiếp tục hoạt động trong trường hợp kết nối mạng không ổn định hoặc không khả dụng

Nếu bạn xây dựng kiến ​​trúc ứng dụng của mình dựa trên các lớp mô hình dữ liệu, thì bạn sẽ làm cho ứng dụng của mình trở nên mạnh mẽ và dễ kiểm tra hơn

Nguồn duy nhất của sự thật

Khi một loại dữ liệu mới được xác định trong ứng dụng của bạn, bạn nên chỉ định một Nguồn thông tin duy nhất (SSOT) cho loại dữ liệu đó. SSOT là chủ sở hữu của dữ liệu đó và chỉ SSOT mới có thể sửa đổi hoặc thay đổi dữ liệu đó. Để đạt được điều này, SSOT hiển thị dữ liệu bằng cách sử dụng loại không thay đổi và để sửa đổi dữ liệu, SSOT hiển thị các chức năng hoặc nhận các sự kiện mà các loại khác có thể gọi

Mô hình này mang lại nhiều lợi ích

  • Nó tập trung tất cả các thay đổi đối với một loại dữ liệu cụ thể ở một nơi
  • Nó bảo vệ dữ liệu để các loại khác không thể giả mạo nó
  • Nó làm cho các thay đổi đối với dữ liệu dễ theo dõi hơn. Do đó, lỗi dễ phát hiện hơn

Trong ứng dụng ưu tiên ngoại tuyến, nguồn gốc của dữ liệu ứng dụng thường là cơ sở dữ liệu. Trong một số trường hợp khác, nguồn gốc của sự thật có thể là ViewModel hoặc thậm chí là UI

Luồng dữ liệu một chiều

Nguồn duy nhất của nguyên tắc sự thật thường được sử dụng trong các hướng dẫn của chúng tôi với mẫu Luồng dữ liệu một chiều (UDF). Trong UDF, trạng thái chỉ chảy theo một hướng. Các sự kiện sửa đổi luồng dữ liệu theo hướng ngược lại

Trong Android, trạng thái hoặc dữ liệu thường chuyển từ các loại phân cấp có phạm vi cao hơn sang các loại có phạm vi thấp hơn. Các sự kiện thường được kích hoạt từ các loại có phạm vi thấp hơn cho đến khi chúng đạt đến SSOT cho loại dữ liệu tương ứng. Ví dụ: dữ liệu ứng dụng thường chuyển từ nguồn dữ liệu sang giao diện người dùng. Các sự kiện của người dùng như nhấn nút chuyển từ giao diện người dùng sang SSOT nơi dữ liệu ứng dụng được sửa đổi và hiển thị ở dạng không thay đổi

Mẫu này đảm bảo tính nhất quán của dữ liệu tốt hơn, ít bị lỗi hơn, dễ gỡ lỗi hơn và mang lại tất cả các lợi ích của mẫu SSOT

Kiến trúc ứng dụng được đề xuất

Phần này trình bày cách cấu trúc ứng dụng của bạn theo các phương pháp hay nhất được đề xuất

Ghi chú. Các đề xuất và phương pháp hay nhất có trong trang này có thể được áp dụng cho nhiều ứng dụng để cho phép chúng mở rộng quy mô, cải thiện chất lượng và độ bền cũng như giúp chúng dễ kiểm tra hơn. Tuy nhiên, bạn nên coi chúng như những hướng dẫn và điều chỉnh chúng cho phù hợp với yêu cầu của bạn khi cần thiết

Xem xét các nguyên tắc kiến ​​trúc phổ biến được đề cập trong phần trước, mỗi ứng dụng nên có ít nhất hai lớp

  • Lớp UI hiển thị dữ liệu ứng dụng trên màn hình
  • Lớp dữ liệu chứa logic nghiệp vụ của ứng dụng của bạn và hiển thị dữ liệu ứng dụng

Bạn có thể thêm một lớp bổ sung gọi là lớp miền để đơn giản hóa và sử dụng lại các tương tác giữa giao diện người dùng và lớp dữ liệu

Theo dõi thói quen google sheet
Hình 1. Sơ đồ kiến ​​trúc ứng dụng điển hình. Ghi chú. Các mũi tên trong sơ đồ trong hướng dẫn này thể hiện sự phụ thuộc giữa các lớp. Ví dụ, lớp miền phụ thuộc vào các lớp lớp dữ liệu.

lớp giao diện người dùng

Vai trò của lớp giao diện người dùng (hoặc lớp trình bày) là hiển thị dữ liệu ứng dụng trên màn hình. Bất cứ khi nào dữ liệu thay đổi, do tương tác của người dùng (chẳng hạn như nhấn nút) hoặc đầu vào bên ngoài (chẳng hạn như phản hồi của mạng), giao diện người dùng sẽ cập nhật để phản ánh các thay đổi

Lớp giao diện người dùng được tạo thành từ hai thứ

  • Các thành phần giao diện người dùng hiển thị dữ liệu trên màn hình. Bạn xây dựng các yếu tố này bằng cách sử dụng các chức năng Chế độ xem hoặc Jetpack Compose
  • Những người nắm giữ trạng thái (chẳng hạn như các lớp ViewModel) giữ dữ liệu, hiển thị nó cho giao diện người dùng và xử lý logic
Theo dõi thói quen google sheet
Hình 2. Vai trò của lớp giao diện người dùng trong kiến ​​trúc ứng dụng

Để tìm hiểu thêm về lớp này, hãy xem trang lớp giao diện người dùng

Lớp dữ liệu

Lớp dữ liệu của ứng dụng chứa logic nghiệp vụ. Logic nghiệp vụ là thứ mang lại giá trị cho ứng dụng của bạn—nó được tạo thành từ các quy tắc xác định cách ứng dụng của bạn tạo, lưu trữ và thay đổi dữ liệu

Lớp dữ liệu được tạo thành từ các kho lưu trữ mà mỗi kho có thể chứa từ 0 đến nhiều nguồn dữ liệu. Bạn nên tạo một lớp kho lưu trữ cho từng loại dữ liệu khác nhau mà bạn xử lý trong ứng dụng của mình. Ví dụ: bạn có thể tạo lớp MoviesRepository cho dữ liệu liên quan đến phim hoặc lớp PaymentsRepository cho dữ liệu liên quan đến thanh toán

Theo dõi thói quen google sheet
Hình 3. Vai trò của lớp dữ liệu trong kiến ​​trúc ứng dụng

Các lớp kho lưu trữ chịu trách nhiệm cho các nhiệm vụ sau

  • Hiển thị dữ liệu cho phần còn lại của ứng dụng
  • Tập trung các thay đổi vào dữ liệu
  • Giải quyết xung đột giữa nhiều nguồn dữ liệu
  • Tóm tắt các nguồn dữ liệu từ phần còn lại của ứng dụng
  • Chứa logic kinh doanh

Mỗi lớp nguồn dữ liệu phải có trách nhiệm làm việc với chỉ một nguồn dữ liệu, có thể là tệp, nguồn mạng hoặc cơ sở dữ liệu cục bộ. Các lớp nguồn dữ liệu là cầu nối giữa ứng dụng và hệ thống cho các thao tác dữ liệu

Để tìm hiểu thêm về lớp này, hãy xem trang lớp dữ liệu

lớp miền

Lớp miền là lớp tùy chọn nằm giữa giao diện người dùng và lớp dữ liệu

Lớp miền chịu trách nhiệm đóng gói logic nghiệp vụ phức tạp hoặc logic nghiệp vụ đơn giản được nhiều ViewModels sử dụng lại. Lớp này là tùy chọn vì không phải ứng dụng nào cũng có những yêu cầu này. Bạn chỉ nên sử dụng nó khi cần—ví dụ: để xử lý sự phức tạp hoặc ưu tiên khả năng sử dụng lại

Theo dõi thói quen google sheet
hinh 4. Vai trò của lớp miền trong kiến ​​trúc ứng dụng

Các lớp trong lớp này thường được gọi là trường hợp sử dụng hoặc trình tương tác. Mỗi trường hợp sử dụng phải có trách nhiệm đối với một chức năng duy nhất. Ví dụ: ứng dụng của bạn có thể có lớp GetTimeZoneUseCase nếu nhiều ViewModels dựa vào múi giờ để hiển thị thông báo phù hợp trên màn hình

Để tìm hiểu thêm về lớp này, hãy xem trang lớp miền

Quản lý sự phụ thuộc giữa các thành phần

Các lớp trong ứng dụng của bạn phụ thuộc vào các lớp khác để hoạt động bình thường. Bạn có thể sử dụng một trong các mẫu thiết kế sau để thu thập các phụ thuộc của một lớp cụ thể

  • Tiêm phụ thuộc (DI). Nội xạ phụ thuộc cho phép các lớp xác định các phụ thuộc của chúng mà không cần xây dựng chúng. Trong thời gian chạy, một lớp khác chịu trách nhiệm cung cấp các phụ thuộc này
  • định vị dịch vụ. Mẫu định vị dịch vụ cung cấp một sổ đăng ký nơi các lớp có thể lấy các phụ thuộc của chúng thay vì xây dựng chúng

Các mẫu này cho phép bạn mở rộng quy mô mã của mình vì chúng cung cấp các mẫu rõ ràng để quản lý các phần phụ thuộc mà không cần sao chép mã hoặc thêm độ phức tạp. Hơn nữa, các mẫu này cho phép bạn nhanh chóng chuyển đổi giữa triển khai thử nghiệm và sản xuất

Chúng tôi khuyên bạn nên làm theo các mẫu tiêm phụ thuộc và sử dụng thư viện Hilt trong ứng dụng Android. Hilt tự động xây dựng các đối tượng bằng cách duyệt cây phụ thuộc, cung cấp đảm bảo thời gian biên dịch cho các phần phụ thuộc và tạo vùng chứa phụ thuộc cho các lớp khung công tác Android

Thực tiễn tốt nhất nói chung

Lập trình là một lĩnh vực sáng tạo và xây dựng ứng dụng Android cũng không ngoại lệ. Có nhiều cách để giải quyết một vấn đề;

Mặc dù các đề xuất sau đây không bắt buộc nhưng trong hầu hết các trường hợp, việc tuân theo chúng giúp cơ sở mã của bạn mạnh mẽ hơn, có thể kiểm tra và bảo trì về lâu dài

Không lưu trữ dữ liệu trong các thành phần ứng dụng

Tránh chỉ định các điểm vào của ứng dụng—chẳng hạn như các hoạt động, dịch vụ và bộ thu quảng bá—làm nguồn dữ liệu. Thay vào đó, chúng chỉ nên phối hợp với các thành phần khác để truy xuất tập hợp con dữ liệu có liên quan đến điểm vào đó. Mỗi thành phần ứng dụng có thời gian tồn tại khá ngắn, tùy thuộc vào sự tương tác của người dùng với thiết bị của họ và tình trạng chung hiện tại của hệ thống

Giảm sự phụ thuộc vào các lớp Android

Các thành phần ứng dụng của bạn phải là các lớp duy nhất dựa trên API SDK khung Android, chẳng hạn như Context hoặc Toast. Trừu tượng hóa các lớp khác trong ứng dụng của bạn khỏi chúng giúp tăng khả năng kiểm tra và giảm sự ghép nối trong ứng dụng của bạn

Tạo ranh giới rõ ràng về trách nhiệm giữa các mô-đun khác nhau trong ứng dụng của bạn

Ví dụ: không trải mã tải dữ liệu từ mạng qua nhiều lớp hoặc gói trong cơ sở mã của bạn. Tương tự, không xác định nhiều trách nhiệm không liên quan—chẳng hạn như bộ nhớ đệm dữ liệu và liên kết dữ liệu—trong cùng một lớp. Làm theo kiến ​​trúc ứng dụng được đề xuất sẽ giúp bạn điều này

Hiển thị càng ít càng tốt từ mỗi mô-đun

Ví dụ: đừng cố gắng tạo lối tắt hiển thị chi tiết triển khai nội bộ từ một mô-đun. Bạn có thể kiếm được một chút thời gian trong thời gian ngắn, nhưng sau đó bạn có khả năng mắc nợ kỹ thuật nhiều lần khi cơ sở mã của bạn phát triển

Tập trung vào cốt lõi độc đáo của ứng dụng để nó nổi bật so với các ứng dụng khác

Đừng phát minh lại bánh xe bằng cách viết đi viết lại cùng một mã soạn sẵn. Thay vào đó, hãy tập trung thời gian và năng lượng của bạn vào những gì làm cho ứng dụng của bạn trở nên độc đáo và để thư viện Jetpack cũng như các thư viện được đề xuất khác xử lý bản mẫu lặp đi lặp lại

Xem xét cách làm cho từng phần của ứng dụng của bạn có thể kiểm tra được một cách riêng biệt

Ví dụ: có API được xác định rõ để tìm nạp dữ liệu từ mạng giúp dễ dàng kiểm tra mô-đun lưu trữ dữ liệu đó trong cơ sở dữ liệu cục bộ. Thay vào đó, nếu bạn trộn logic từ hai mô-đun này vào một nơi hoặc phân phối mã mạng của bạn trên toàn bộ cơ sở mã của bạn, thì việc kiểm tra hiệu quả sẽ trở nên khó khăn hơn nhiều nếu không muốn nói là không thể.

Các loại chịu trách nhiệm về chính sách tương tranh của chúng

Nếu một loại đang thực hiện công việc chặn trong thời gian dài, thì nó phải chịu trách nhiệm chuyển tính toán đó sang đúng luồng. Loại cụ thể đó biết loại tính toán mà nó đang thực hiện và nó sẽ được thực thi trong luồng nào. Các loại phải an toàn chính, nghĩa là chúng an toàn để gọi từ luồng chính mà không chặn nó

Duy trì càng nhiều dữ liệu mới và phù hợp càng tốt

Bằng cách đó, người dùng có thể tận hưởng chức năng ứng dụng của bạn ngay cả khi thiết bị của họ ở chế độ ngoại tuyến. Hãy nhớ rằng không phải tất cả người dùng của bạn đều thích kết nối liên tục, tốc độ cao—và ngay cả khi họ làm như vậy, họ có thể nhận tín hiệu kém ở những nơi đông người

Lợi ích của Kiến trúc

Có một Kiến trúc tốt được triển khai trong ứng dụng của bạn mang lại rất nhiều lợi ích cho dự án và nhóm kỹ thuật

  • Nó cải thiện khả năng bảo trì, chất lượng và độ bền của ứng dụng tổng thể
  • Nó cho phép ứng dụng mở rộng quy mô. Nhiều người hơn và nhiều nhóm hơn có thể đóng góp vào cùng một cơ sở mã với xung đột mã tối thiểu
  • Nó giúp giới thiệu. Khi Kiến trúc mang lại sự nhất quán cho dự án của bạn, các thành viên mới của nhóm có thể nhanh chóng bắt kịp tốc độ và hiệu quả hơn trong khoảng thời gian ngắn hơn
  • Nó dễ dàng hơn để kiểm tra. Một Kiến trúc tốt khuyến khích các loại đơn giản hơn thường dễ kiểm tra hơn
  • Lỗi có thể được điều tra một cách có phương pháp với các quy trình được xác định rõ

Đầu tư vào Kiến trúc cũng có tác động trực tiếp đến người dùng của bạn. Họ được hưởng lợi từ ứng dụng ổn định hơn và nhiều tính năng hơn nhờ đội ngũ kỹ thuật làm việc hiệu quả hơn. Tuy nhiên, Kiến trúc cũng đòi hỏi đầu tư thời gian trước. Để giúp bạn chứng minh thời gian này với phần còn lại của công ty, hãy xem các nghiên cứu điển hình này, nơi các công ty khác chia sẻ câu chuyện thành công của họ khi có một kiến ​​trúc tốt trong ứng dụng của họ

Mẫu

Các mẫu Google sau đây chứng minh kiến ​​trúc ứng dụng tốt. Hãy khám phá chúng để xem hướng dẫn này trong thực tế