You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从数据库获取购物列表时圆形加载进度条不显示问题修复

问题修复:加载购物列表时正确显示圆形进度条

问题分析

当前代码存在两个核心问题:

  1. ViewModel中手动管理的loading状态逻辑失效:getAllShoppingListItemsUseCase()返回Flow的赋值操作是同步的,导致loading.value = false被立即执行,进度条还未显示就被关闭。
  2. 空列表提示提前触发:LazyPagingItems的itemCount在加载过程中可能临时为0,导致加载完成前就显示空文本提示。

解决方案

我们可以直接利用Paging库自带的加载状态管理来替代手动loading变量,同时调整空提示的显示条件,确保仅在加载完成且无数据时才展示。

1. 修改ViewModel:移除手动loading状态

@HiltViewModel
class ShoppingListScreenViewModel @Inject constructor(
    private val getAllShoppingListItemsUseCase: GetAllShoppingListItemsUseCase
) {
    // 直接暴露Paging Flow,无需包装为State<Flow?>
    val shoppingListItemsFlow: Flow<PagingData<ShoppingListItem>> = 
        getAllShoppingListItemsUseCase().distinctUntilChanged()
}

2. 修改Composable:基于LoadState控制进度条与空提示

fun ShoppingListScreen(
    navController: NavHostController,
    shoppingListScreenViewModel: ShoppingListScreenViewModel,
    sharedViewModel: SharedViewModel
) {
    val scope = rememberCoroutineScope()
    val screenHeight = LocalConfiguration.current.screenHeightDp.dp
    // 直接收集Flow为LazyPagingItems
    val allItems = shoppingListScreenViewModel.shoppingListItemsFlow.collectAsLazyPagingItems()
    // 通过Paging的LoadState判断是否处于加载状态
    val isLoading = allItems.loadState.refresh is LoadState.Loading

    Scaffold(
        topBar = {
            CustomAppBar(
                title = "购物列表",
                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,
        isFloatingActionButtonDocked = false,
        bottomBar = { BottomNavigationBar(navController = navController) }
    ) { paddingValues ->
        Box(modifier = Modifier.padding(paddingValues)) {
            LazyColumn(modifier = Modifier.fillMaxSize()) {
                // 仅在加载完成且无数据时显示空提示
                if (allItems.itemCount == 0 && allItems.loadState.refresh is LoadState.NotLoading) {
                    item { 
                        Text(
                            "这个购物列表里还没有任何物品。",
                            modifier = Modifier.fillMaxWidth().padding(16.dp),
                            textAlign = TextAlign.Center
                        ) 
                    }
                }

                items(allItems, key = { item -> item.id }) { item ->
                    item?.let {
                        ShoppingListScreenItem(
                            navController = navController,
                            item = it,
                            sharedViewModel = sharedViewModel
                        ) { isChecked ->
                            scope.launch {
                                shoppingListScreenViewModel.changeItemChecked(it, isChecked)
                            }
                        }
                    }
                }

                item { Spacer(modifier = Modifier.height(70.dp)) }
            }

            // 根据Paging加载状态显示进度条
            if (isLoading) {
                ConditionalCircularProgressBar(isDisplayed = true)
            }
        }
    }
}

关键优化点

  • 依赖Paging原生状态:用LazyPagingItems.loadState.refresh判断加载状态,比手动管理loading变量更准确,Paging会自动跟踪加载的开始、成功、失败状态。
  • 延迟空提示显示:只有当加载完成且确认无数据时才展示空文本,避免加载过程中出现一闪而过的提示。
  • 安全处理空Item:LazyPagingItems在加载过程中可能返回null,通过item?.let避免空指针异常。
  • 修复布局遮挡:应用Scaffold返回的paddingValues,确保内容不会被TopBar或BottomBar遮挡。

内容的提问来源于stack exchange,提问作者Raj Narayanan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:10:25