0

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?"


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


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí