class HomeViewModel(
savedStateHandle: SavedStateHandle,
private val categoryRepository: CategoryRepository,
private val expenseRepository: ExpenseRepository
): ViewModel() {
private val month: Int = savedStateHandle[HomeDestination.monthArgs] ?: Calendar.MONTH
private val year: Int = savedStateHandle[HomeDestination.yearArgs] ?: Calendar.YEAR
private val _categories: Flow<List<Category>> = categoryRepository.getAllCategoriesStream()
private val _expenses: Flow<List<Expense>> = expenseRepository.getAllExpensesBetweenStream(
LocalDate.of(year, month, 1).toEpochDay(),
LocalDate.of(year, if (month + 1 == 13) 1 else month + 1, 1).toEpochDay()
)
private var _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
data class UiState(
val categories: List<CategoryUiState> = listOf(),
val expenses: List<ExpenseUiState> = listOf()
)
}
I want to link the value of _expenses
to expenses
in the UiState
and do it so it updates the expenses if _expenses
content updates.
Assuming the issue is not how you can store an Expense
object as an ExpenseUiState
, I'll expect there to be some helper function that creates a proper UiState
from a Category
and an Expense
. Let's call that UiState.of(...)
.
Then you can replace _uiState
and uiState
with this:
val uiState: StateFlow<UiState> = combine(_categories, _expenses) { categories, expenses ->
UiState.of(categories, expenses)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = UiState.Default,
)
This combines multiple flows into a single flow using UiState.of
to create the resulting content. Then it is converted to a StateFlow
. That needs an initial value, so I invented a UiState.Default
. Replace that with whatever you want the flow to return until the first values are produced from _categories
and _expenses
. Could be null
if you wanted.