Đang tải...

Migrate từ LiveData sang StateFlow trong Android: Hướng dẫn thực tế cho dự án production

27/05/2026
4 phút đọc
Migrate từ LiveData sang StateFlow trong Android: Hướng dẫn thực tế cho dự án production
> "StateFlow là tương lai. Nhưng migrate từ LiveData như thế nào để không phá vỡ architecture hiện tại?" --- ![](https://images.viblo.asia/913b5b93-ab6b-4946-9959-b4aedfaf1bb1.png...

"StateFlow là tương lai. Nhưng migrate từ LiveData như thế nào để không phá vỡ architecture hiện tại?"


Mở đầu

Nếu bạn đang maintain một Android project cũ, rất có thể bạn đang có:

ViewModel + LiveData + XML

Và giờ team muốn migrate sang:

ViewModel + StateFlow + Compose (hoặc XML)

Câu hỏi là:

  • có cần rewrite toàn bộ không?
  • migrate từng phần được không?
  • có rủi ro gì?

Tin tốt:

Bạn hoàn toàn có thể migrate incremental.

Không cần rewrite toàn bộ app.


1. Vì sao nên migrate?

Google hiện ưu tiên:

  • Kotlin Coroutines
  • Flow
  • StateFlow

Nguồn: https://developer.android.com/kotlin/flow/stateflow-and-sharedflow

Lý do:

✅ coroutine-native ✅ tốt hơn cho Compose ✅ mạnh hơn về reactive stream ✅ dễ scale hơn cho architecture lớn


2. Một project LiveData thường trông như thế này

Ví dụ:

class UserViewModel : ViewModel() {

 private val _users = MutableLiveData<List<User>>()
 val users: LiveData<List<User>> = _users

 fun loadUsers() {
 _users.value = repository.getUsers()
 }
}

UI observe:

viewModel.users.observe(viewLifecycleOwner) {
 adapter.submitList(it)
}

Hoạt động tốt.

Nhưng bị giới hạn:

  • không coroutine-first
  • khó combine stream
  • khó test hơn

3. Step 1: thay MutableLiveData bằng MutableStateFlow

Trước:

private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> = _users

Sau:

private val _users =
 MutableStateFlow<List<User>>(emptyList())

val users: StateFlow<List<User>> = _users

Lưu ý:

StateFlow bắt buộc có initial value.

Ví dụ:

emptyList()
false
UiState()
null

4. Step 2: thay .value

Trước:

_users.value = repository.getUsers()

Sau:

_users.value = repository.getUsers()

Tin vui:

cú pháp gần như giống hệt.

Đây là lý do migrate khá dễ.


5. Step 3: update UI layer

Trước:

viewModel.users.observe(
 viewLifecycleOwner
) {
 adapter.submitList(it)
}

Sau:

viewLifecycleOwner.lifecycleScope.launch {
 repeatOnLifecycle(Lifecycle.State.STARTED) {
 viewModel.users.collect {
 adapter.submitList(it)
 }
 }
}

Quan trọng:

Luôn dùng:

repeatOnLifecycle()

để tránh memory leak.

Google khuyến nghị cách này.


6. Với Jetpack Compose thì còn dễ hơn

val users by viewModel.users
 .collectAsState()

Done.

Không cần observe.

Đây là lý do StateFlow cực hợp với Compose.


7. Nếu đang dùng XML thì sao?

Không cần migrate UI ngay.

Bạn có thể bridge:

val usersLiveData =
 users.asLiveData()

Ví dụ:

private val _users =
 MutableStateFlow<List<User>>(emptyList())

val usersLiveData =
 _users.asLiveData()

UI cũ vẫn dùng:

observe()

=> migrate dần từng màn.

Đây là chiến lược tốt nhất cho production app.


8. Handling Loading + Error tốt hơn

LiveData thường viết:

val loading = MutableLiveData<Boolean>()
val users = MutableLiveData<List<User>>()
val error = MutableLiveData<String>()

Rất dễ rối.

StateFlow nên dùng:

data class UiState(
 val loading: Boolean = false,
 val users: List<User> = emptyList(),
 val error: String? = null
)

ViewModel:

private val _uiState =
 MutableStateFlow(UiState())

Ưu điểm:

✅ clean hơn ✅ scalable hơn ✅ dễ test hơn


9. Các lỗi migrate phổ biến


Lỗi 1: quên initial value

Sai:

MutableStateFlow<List<User>>()

Sẽ compile fail.

Phải là:

MutableStateFlow(emptyList())

Lỗi 2: quên repeatOnLifecycle

Sai:

launch {
 flow.collect { }
}

Có thể gây leak.

Đúng:

repeatOnLifecycle(...)

Lỗi 3: migrate tất cả cùng lúc

Không nên.

Hãy migrate theo module:

Auth
→ Home
→ Profile
→ Settings

An toàn hơn nhiều.


10. Strategy migrate production

Mình khuyến nghị:

Phase 1

Repository trả về Flow


Phase 2

ViewModel đổi sang StateFlow


Phase 3

UI vẫn dùng asLiveData()


Phase 4

Migrate UI sang collect()


Phase 5

Remove LiveData hoàn toàn


Đây là cách ít rủi ro nhất.


11. Recommendation 2026

Nếu app mới:

StateFlow + SharedFlow

Nếu app cũ:

Migrate từng bước

Không rewrite toàn bộ.


Kết luận

Migrate từ LiveData sang StateFlow:

❌ không khó ❌ không cần rewrite app

Chỉ cần:

  • đúng strategy
  • migrate từng bước
  • test kỹ từng màn

Đó là cách production team thực tế đang làm.


References

1. Android Developers — StateFlow and SharedFlow

https://developer.android.com/kotlin/flow/stateflow-and-sharedflow


2. Android Developers — LiveData

https://developer.android.com/topic/libraries/architecture/livedata


3. Official Kotlin Coroutines

https://kotlinlang.org/docs/flow.html

📚 Nguồn: Viblo

Bình luận

0 bình luận

Email không hiển thị công khai.

Chưa có bình luận nào. Hãy là người đầu tiên bình luận.

Chia sẻ bài viết

Cần tư vấn?

Liên hệ với chúng tôi để được hỗ trợ

Liên hệ ngay

Bài viết liên quan

Proxy hoạt động ở tầng nào trong mô hình TCP/IP? HTTP Proxy Và SOCKS5 nằm ở đâu?
09/06/2026

Proxy hoạt động ở tầng nào trong mô hình TCP/IP? HTTP Proxy Và SOCKS5 nằm ở đâu?

Proxy hoạt động ở tầng nào? Sau khi đã đi qua các tầng mạng như Physical Layer, Data Link Layer, Internet Layer, Transport Layer và Application Layer, ta có thể nhìn Proxy rõ ...

Đọc thêm
Red Team RAG: Khi mỗi pipeline là một đường hầm tối – Phần 2: Đầu độc dòng chảy – Từ ingestion đến sụp đổ
09/06/2026

Red Team RAG: Khi mỗi pipeline là một đường hầm tối – Phần 2: Đầu độc dòng chảy – Từ ingestion đến sụp đổ

## Lời mở đầu: Bạn đã vào hầm. Bây giờ, hãy đầu độc dòng nước. Ở phần 1, chúng ta đã đứng trước **cửa hầm**, học cách đọc bản đồ pipeline RAG, v...

Đọc thêm
Vì sao giá trị truyền thống luôn được đặt lên hàng đầu
09/06/2026

Vì sao giá trị truyền thống luôn được đặt lên hàng đầu

Giá trị truyền thống không chỉ là yếu tố mang tính hoài niệm, mà còn đóng vai trò nền tảng trong việc định hình bản sắc và chiều sâu của một công trình ...

Đọc thêm

Bắt đầu dự án của bạn

Hãy để Flash Dev đồng hành cùng bạn

Liên hệ ngay