How to check if PadingData<T> is empty in ViewModel?

352 Views Asked by At

I'm using Paging 3 with a Room database in my Android app. Currently, I have a sealed class which contains the Loading, Empty, Error states, and a Success state which receives the retrieved PagingData<ShoppingListItem> list data. In the ViewModel, I want to assign the Empty state if the PagingData list is empty and display a Compose UI message stating that the shopping list is empty. But, I'm not sure how to do this? How can I check if PagingData<ShoppingListItem> is empty in the ViewModel?

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()

   init {
      getAllShoppingListItemsFromDb()
   }

   private fun getAllShoppingListItemsFromDb() {
      viewModelScope.launch {
          _shoppingListItemsState.value = getAllShoppingListItemsUseCase().distinctUntilChanged()
          _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 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 -> {}
            }
        }
    }
}
0

There are 0 best solutions below