0

I have a LazyColumn that collects a Flow<PagingData<ShoppingListItem>>? from the ViewModel, but the itemCount property of the collected state reports an empty list with 0 items at first briefly before it reports the actual number of items in the database. How can I fix this?

Logcat Output

2022-11-17 06:41:06.187 I/@@successItemsCount: 0
2022-11-17 06:41:06.447 I/@@successItemsCount: 0
2022-11-17 06:41:06.501 I/@@successItemsCount: 11

Sealed Class

sealed class ListItemsState {
    object Loading : 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()

                    Log.i("@@successItemsCount", successItems.itemCount.toString())

                    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 -> {}
            }
        }
    }
}
Raj Narayanan
  • 2,443
  • 4
  • 24
  • 43
  • I have tried the paging 3 with jetpack compose its too buggy. Its promise that it can handle large data set does not actually works. I have tried it and it crashes all the time not very stable causes out of memory. The list I have tested is like a instagram newsfeed. Each item has photo and text – Renz Carlo Nov 21 '22 at 05:08
  • I ended up creating my own pagination library – Renz Carlo Nov 21 '22 at 05:10

1 Answers1

0

Does your UI appear empty? There is an open bug within Compose: https://issuetracker.google.com/issues/177245496

@Composable
fun rememberLazyListState(empty: Boolean = false): LazyListState {
    return if (empty) {
        // Return a different state instance
        remember { LazyListState(0, 0) }
    } else {
        // Return restored state
        androidx.compose.foundation.lazy.rememberLazyListState()
    }
}

Use this lazyListState rememberLazyListState(empty = items.itemCount == 0)

Devesh
  • 33
  • 6