Phân biệt Flow và StateFlow trong lập trình Android
Câu chuyện về Flow và StateFlow
Hãy tưởng tượng bạn đang ở một quán cà phê để tham gia một cuộc họp. Có hai kiểu nhân viên phục vụ, tương ứng với Flow và StateFlow:
Flow: Người phục vụ chỉ chuyển tiếp từng thông điệp một
Bạn gọi một ly cà phê và ngồi chờ.
Người phục vụ (Flow) chỉ mang đến từng thông tin một khi có, ví dụ:
- "Ly cà phê của bạn đang được pha chế."
- "Ly cà phê của bạn đang được bưng ra."
- "Đây là cà phê của bạn, mời bạn dùng."
Nếu bạn đến muộn, bạn sẽ không nhận được các thông tin đã xảy ra trước đó, bởi vì người phục vụ chỉ cung cấp thông tin hiện tại.
Đặc điểm Flow trong câu chuyện:
- Flow phát ra luồng dữ liệu từng cái một, theo thứ tự thời gian.
- Flow không giữ lại thông tin nào nếu bạn đến muộn.
StateFlow: Người phục vụ luôn cập nhật trạng thái hiện tại
Bây giờ, giả sử bạn đang tham gia một cuộc họp trong phòng riêng, và nhân viên phục vụ (StateFlow) sẽ luôn đảm bảo bạn biết trạng thái hiện tại của quán cà phê.
Ví dụ:
- Lúc bạn bước vào, nhân viên báo ngay: "Quán đang pha cà phê."
- Khi pha xong: "Cà phê của bạn đã sẵn sàng."
- Nếu bạn rời phòng họp và quay lại sau, nhân viên sẽ vẫn báo: "Cà phê của bạn đang chờ trên bàn."
Đặc điểm StateFlow trong câu chuyện:
- StateFlow luôn giữ trạng thái mới nhất, và bất kỳ ai tham gia vào đều nhận được trạng thái hiện tại.
- Nó không phát từng thông điệp riêng lẻ theo thời gian, mà chỉ cho bạn biết hiện tại đang ở đâu.
Kết luận từ câu chuyện
- Flow giống như một luồng thông điệp diễn ra theo thời gian, không lưu trữ quá khứ.
- StateFlow giống như bảng thông báo hiện trạng, luôn cập nhật trạng thái mới nhất và bất kỳ ai tham gia sau đều thấy trạng thái hiện tại.
Ứng dụng thực tế:
- Dùng Flow khi cần xử lý chuỗi sự kiện hoặc dữ liệu liên tục, ví dụ: theo dõi log sự kiện.
- Dùng StateFlow khi cần lưu và cập nhật trạng thái, ví dụ: quản lý trạng thái UI trong ViewModel.
Giải thích rõ hơn để bạn nắm rõ cách hoạt động của Flow và StateFlow trong trường hợp code thực tế:
Flow:
- Đặc điểm: Flow là "cold stream" (luồng lạnh), nghĩa là nó chỉ bắt đầu thu thập dữ liệu khi có một "collector" đang hoạt động (đang
collect
). - Hoạt động: Nếu collector không còn hoạt động (như khi
Activity
hoặcFragment
bị dừng do vào trạng tháipaused
hoặcstopped
), thì dữ liệu sẽ không được thu thập nữa. Tức là, Flow sẽ không lưu trữ giá trị trước đó hoặc giữ trạng thái. - Kết quả: Dữ liệu sẽ bị mất nếu không có collector hoạt động tại thời điểm đó.
StateFlow:
- Đặc điểm: StateFlow là "hot stream" (luồng nóng) và giữ trạng thái hiện tại. Nó lưu giữ giá trị mới nhất và sẽ gửi giá trị đó đến collector bất cứ khi nào collector trở lại hoạt động.
- Hoạt động: Ngay cả khi
Activity
hoặcFragment
bị dừng, StateFlow vẫn lưu giữ giá trị hiện tại. KhiActivity
hoặcFragment
được khởi động lại, collector sẽ nhận được giá trị cuối cùng.
Ví dụ minh họa
Hãy tưởng tượng bạn có một luồng Flow và StateFlow truyền thông báo từ một ViewModel:
Với Flow:
- Người gửi (Flow) liên tục phát ra các thông điệp:
"A"
,"B"
,"C"
,... - Khi bạn ở trạng thái hoạt động (active), bạn nhận được
"A"
,"B"
. - Khi bạn chuyển sang trạng thái tạm dừng (paused), bạn sẽ không nhận được thông báo
"C"
,"D"
. - Khi bạn quay lại trạng thái hoạt động, Flow không phát lại các thông báo đã bị bỏ lỡ, nó chỉ gửi thông điệp mới tiếp theo (nếu có).
Với StateFlow:
- Người gửi (StateFlow) phát ra thông điệp cuối cùng:
"C"
. - Khi bạn chuyển sang trạng thái tạm dừng (paused), StateFlow vẫn lưu trữ trạng thái cuối cùng (
"C"
). - Khi bạn quay lại trạng thái hoạt động, StateFlow gửi lại giá trị cuối cùng (
"C"
) ngay lập tức. - Nếu sau đó người gửi phát thêm
"D"
, bạn sẽ nhận được"D"
ngay khi nó được phát ra.
Tóm tắt
Flow | StateFlow |
---|---|
Không lưu trạng thái. | Luôn giữ trạng thái cuối cùng. |
Không phát dữ liệu nếu collector không hoạt động. | Phát lại giá trị mới nhất khi collector hoạt động. |
Phù hợp với luồng dữ liệu một lần (one-shot). | Phù hợp với trạng thái liên tục (state-driven). |
Do đó, trong trường hợp Activity
bị tạm dừng hoặc dừng hẳn:
- Flow sẽ không nhận thông điệp.
- StateFlow sẽ giữ giá trị hiện tại và gửi lại khi collector trở lại hoạt động.
Nhận xét
Đăng nhận xét