aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh hoạ React Native gọi API và hiển thị loading error empty success state

Thiết kế offline-first cho app mobile: bắt đầu từ trạng thái dữ liệu

Suong Nguyen by Suong Nguyen
21/10/2026
in Lập trình Mobile
0
585
SHARES
3.3k
VIEWS
Summarize with ChatGPTShare to Facebook

Người dùng mở danh sách công việc trong thang máy. Mạng không có, nhưng họ đã xem danh sách này trước đó. Nếu app chỉ hiện spinner rồi báo lỗi, sản phẩm đã bỏ phí dữ liệu còn nằm trên thiết bị.

Offline-first bắt đầu từ câu hỏi: người dùng vẫn làm được việc gì khi chưa liên lạc được với server? Bài này trình bày thiết kế áp dụng cho nhiều nền tảng, tham chiếu kiến trúc Android ngày 21/10/2026. Đây là hướng dẫn thiết kế, chưa phải một thư viện đồng bộ hoàn chỉnh.

1. Đừng gộp mọi tình huống thành “offline”

Ba trạng thái dưới đây cần UI và cách xử lý khác nhau:

Trạng thái Người dùng cần hiểu gì?
Có dữ liệu đã lưu, chưa tải được bản mới Vẫn đọc được; dữ liệu có thể chưa cập nhật
Chưa từng có dữ liệu, hiện không tải được Chưa thể hiển thị nội dung; cần thử lại
Đã thay đổi ở máy, server chưa xác nhận Thao tác đang chờ đồng bộ hoặc cần xử lý lỗi

Một dòng trạng thái “Cập nhật lần cuối lúc 14:05” thường có ý nghĩa hơn chỉ một biểu tượng mất mạng. Hãy hiển thị thời gian từ trạng thái dữ liệu thật, không cập nhật nhãn khi việc làm mới thất bại.

2. Chọn một đường đọc dữ liệu nhất quán

Hướng dẫn offline-first của Android đặt nguồn dữ liệu local làm nguồn đọc chuẩn cho các lớp phía trên. Kết quả tải từ mạng được đưa vào local, rồi UI nhận trạng thái mới từ đó.

Bạn có thể bắt đầu với sơ đồ:

UI <- Repository <- Local database
                      ^
                      |
                 Đồng bộ dữ liệu
                      |
                   Network

Vai trò của repository là cung cấp giao diện dữ liệu phù hợp cho phần còn lại của app; chi tiết phối hợp nhiều nguồn nên được giữ ở lớp dữ liệu. Xem thêm tài liệu data layer.

Ví dụ, màn hình danh sách không cần tự quyết định lấy mảng nào giữa cache và response mới. Nó quan sát danh sách từ repository và nhận thêm trạng thái làm mới. Cách tổ chức này giúp bạn viết cùng một hành vi hiển thị cho cả lúc có và không có mạng.

3. Biểu diễn trạng thái thay vì suy đoán từ một boolean

Đây là kiểu dữ liệu minh họa bằng TypeScript, không phụ thuộc framework UI:

type SyncState =
  | { kind: 'synced'; syncedAt: string }
  | { kind: 'pending'; operationId: string }
  | { kind: 'failed'; operationId: string; message: string };

type Task = {
  id: string;
  title: string;
  completed: boolean;
  sync: SyncState;
};

pending cần có dấu vết thao tác để khi người dùng mở lại app, bạn còn biết việc gì chưa được xác nhận. Một biến isOnline không cho biết request cuối cùng đã thành công hay thao tác đã được server ghi nhận chưa.

Với ví dụ công việc cá nhân, app có thể lưu thay đổi và bản ghi thao tác chờ trong cùng transaction local. Nếu app đóng ngay sau đó, lần mở tiếp theo vẫn biết cần đồng bộ gì. Đây là một lựa chọn thiết kế đề xuất; cách thực hiện transaction phụ thuộc database của dự án.

4. Quyết định cách ghi theo từng tính năng

Bạn không cần cho phép mọi hành động chạy offline ngay từ đầu. Hãy phân loại:

  • Đọc dữ liệu đã có: hiển thị bản lưu và cho biết nó có thể đã cũ.
  • Sửa ghi chú cá nhân: có thể lưu local rồi đồng bộ nếu yêu cầu sản phẩm chấp nhận.
  • Hành động cần xác nhận tức thời từ hệ thống: mô tả rõ điều kiện cần mạng và giữ trạng thái chưa hoàn tất cho đến khi có kết quả.

Nếu cho phép gửi lại thao tác, client và server cần thống nhất cách nhận diện cùng một thao tác để tránh ghi lặp. Đừng coi một request timeout là bằng chứng rằng server chưa xử lý nó. Trước khi triển khai phần ghi offline, hãy thống nhất contract đồng bộ và trường hợp xung đột với phía backend.

5. Xử lý xung đột bằng quy tắc sản phẩm

Hai thiết bị có thể sửa cùng một công việc. Quy tắc “bản ghi đến sau thắng” dễ mô tả, nhưng có thể làm mất một thay đổi mà người dùng còn cần. Với dữ liệu quan trọng, bạn có thể cần giữ phiên bản, phát hiện xung đột hoặc cho người dùng hợp nhất nội dung.

Tài liệu Android nêu versioning và các chiến lược giải quyết xung đột. Với team nhỏ, nên chọn một trường hợp cụ thể để viết thành ví dụ: thiết bị A sửa tiêu đề, thiết bị B đánh dấu hoàn thành, cả hai đồng bộ theo thứ tự khác nhau. Kết quả mong muốn cần được quyết định trước khi viết worker retry.

Checklist kiểm tra

  1. Mở app lần đầu khi không có mạng: có hướng dẫn thử lại, không spinner vô hạn.
  2. Đã tải dữ liệu rồi tắt mạng: nội dung đã lưu vẫn đọc được.
  3. Tạo thao tác offline rồi đóng app: thao tác chờ còn tồn tại sau khi mở lại.
  4. Mạng chập chờn trong lúc đồng bộ: không nhân đôi thao tác hoặc báo thành công quá sớm.
  5. Hai thiết bị sửa cùng bản ghi: hành vi đúng quy tắc xung đột đã thống nhất.

Đây là các kịch bản kiểm thử đề xuất, không phải kết quả thử một ứng dụng cụ thể. Hãy bắt đầu với một màn hình đọc offline tốt, rồi mở rộng sang ghi và đồng bộ theo mức độ cần thiết của sản phẩm.

Nguồn tham khảo

  • Android Developers: Build an offline-first app.
  • Android Developers: Data layer.
Tags: Đồng bộ dữ liệuMobileOffline-first
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh hoạ điều hướng giữa các màn hình trong React Native bằng stack và tab

Deep link mobile an toàn: đúng domain chưa đủ, còn route và quyền đọc

by Suong Nguyen
22/10/2026
0

Tách xác minh domain, phân tích route và kiểm tra quyền để link mở đúng màn hình mà không tự cấp quyền truy cập dữ liệu.

Minh họa ứng dụng React Native kết nối nhiều SDK như analytics, maps, authentication, payment và push notification

Tích hợp SDK trong React Native: quy trình thực chiến từ cài đặt đến release

by admin
28/08/2026
2

Hướng dẫn tích hợp SDK trong React Native: cấu hình Android, iOS, API key, permission, adapter, Analytics, Crashlytics, Maps, Payment, Auth và checklist release.

Minh họa Firebase Cloud Messaging gửi push notification tới ứng dụng React Native trên Android và iOS

Hướng dẫn tích hợp Firebase Cloud Messaging (FCM) vào React Native từ A-Z

by admin
02/08/2026
0

Hướng dẫn tích hợp Firebase Cloud Messaging vào React Native từ A-Z: Android, iOS/APNs, quyền notification, FCM token, foreground, background và backend.

Minh họa các hook nâng cao trong React Native kết nối với ứng dụng mobile

Các hook nâng cao trong React Native: dùng đúng để code gọn và tối ưu hiệu năng

by admin
30/07/2026
0

Hướng dẫn chi tiết các hook nâng cao trong React Native: useReducer, useContext, useMemo, useCallback, useRef, transition, custom hook và tối ưu hiệu năng.

Next Post
Minh hoạ state thay đổi và làm giao diện React Native cập nhật lại

Bài tập phỏng vấn React: sửa bộ lọc danh sách bị lệch state

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native: tránh bàn phím che form với KeyboardAvoidingView và ScrollView
  • Phỏng vấn JavaScript: giải thích event loop, microtask và async/await
  • Deep link mobile an toàn: đúng domain chưa đủ, còn route và quyền đọc

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply