Depending on the status of PagingData<ShoppingListItem>
, I'm updating the loading status in the ViewModel
with a sealed class. As I don't know how to check if PagingData<ShoppingListItem>
is emtpy in the ViewModel
, I'm just collecting the PagingData
and calling the .map
function on it to add it to a mutableList
. I then update the loading state as Emtpy
if the list is empty and display an empty message in the UI. The problem is all the code below the collect()
method call does not execute, and the circular progress bar does not go away. Even a Log
statement below it does not execute. How can I make this work?
Sealed Class
sealed class ListItemsState {
object Loading : ListItemsState()
object Empty : ListItemsState()
object Error : ListItemsState()
data class Success(val allItems: Flow<PagingData<ShoppingListItem>>?) : ListItemsState()
}
ViewModel
@HiltViewModel
class ShoppingListScreenViewModel @Inject constructor(
private val getAllShoppingListItemsUseCase: GetAllShoppingListItemsUseCase
) {
private val _shoppingListItemsState = mutableStateOf<Flow<PagingData<ShoppingListItem>>?>(null)
private val _listItemsLoadingState = MutableStateFlow<ListItemsState>(ListItemsState.Loading)
val listItemsLoadingState = _listItemsLoadingState.asStateFlow()
private val tempList = mutableListOf<ShoppingListItem>()
init {
viewModelScope.launch {
getAllShoppingListItemsFromDb()
}
}
private suspend fun getAllShoppingListItemsFromDb() {
_shoppingListItemsState.value = getAllShoppingListItemsUseCase().distinctUntilChanged()
_shoppingListItemsState.value?.collect {
it.map { shoppingListItem ->
tempList.add(shoppingListItem)
}
} //everything below this line does not execute
Log.i("@@sealed", tempList.isEmpty().toString())
when {
tempList.isEmpty() -> _listItemsLoadingState.value = ListItemsState.Empty
else -> _listItemsLoadingState.value =
ListItemsState.Success(_shoppingListItemsState.value)
}
}
}
ShoppingListScreen Composable
@Composable
fun ShoppingListScreen(
navController: NavHostController,
shoppingListScreenViewModel: ShoppingListScreenViewModel,
sharedViewModel: SharedViewModel
) {
val screenHeight = LocalConfiguration.current.screenHeightDp.dp
val allItemsState = shoppingListScreenViewModel.listItemsLoadingState.collectAsState().value
Scaffold(
topBar = {
CustomAppBar(
title = "Shopping List",
titleFontSize = 20.sp,
appBarElevation = 4.dp,
navController = navController
)
},
floatingActionButton = {
FloatingActionButton(
onClick = {
shoppingListScreenViewModel.setStateValue(SHOW_ADD_ITEM_DIALOG_STR, true)
},
backgroundColor = Color.Blue,
contentColor = Color.White
) {
Icon(Icons.Filled.Add, "")
}
},
backgroundColor = Color.White,
// Defaults to false
isFloatingActionButtonDocked = false,
bottomBar = { BottomNavigationBar(navController = navController) }
) {
Box {
when (allItemsState) {
is ListItemsState.Loading -> ConditionalCircularProgressBar(isDisplayed = true)
is ListItemState.Empty -> Text("Empty!")
is ListItemsState.Error -> Text("Error!")
is ListItemsState.Success -> {
ConditionalCircularProgressBar(isDisplayed = false)
val successItems = allItemsState.allItems?.collectAsLazyPagingItems()
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.height(screenHeight)
) {
items(
items = successItems!!,
key = { item ->
item.id
}
) { item ->
ShoppingListScreenItem(
navController = navController,
item = item,
sharedViewModel = sharedViewModel
) { isChecked ->
scope.launch {
shoppingListScreenViewModel.changeItemChecked(item!!, isChecked)
}
}
}
item { Spacer(modifier = Modifier.padding(screenHeight - (screenHeight - 70.dp))) }
}
}
else -> {}
}
}
}
}