کتابخانه «صفحهبندی» وضعیت درخواستهای بارگیری را برای دادههای صفحهبندیشده ردیابی میکند و آن را ازطریق کلاس LoadState نشان میدهد.
سیگنال LoadState جداگانهای برای هر
LoadType و نوع منبع داده
(PagingSource یا
RemoteMediator) ارائه میشود.
شیء CombinedLoadStates
ارائهشده توسط شنونده اطلاعاتی درباره وضعیت بارگیری
از همه این سیگنالها ارائه میدهد. میتوانید از این اطلاعات دقیق برای نمایش
نشانگرهای بارگیری مناسب به کاربران استفاده کنید.
درحال بار کردن استانها
کتابخانه «صفحهبندی» وضعیت بارگیری را برای استفاده در واسط کاربر ازطریق شیء
LoadState نشان میدهد. LoadState اشیاء بسته به وضعیت بارگیری فعلی، یکی از سه شکل را به خود میگیرند:
- اگر عملیات بارگیری فعالی وجود نداشته باشد و خطایی رخ نداده باشد،
LoadStateیک شیءLoadState.NotLoadingاست. این زیرکلاس همچنین شامل ویژگیendOfPaginationReachedاست که نشان میدهد آیا به پایان صفحهبندی رسیدهایم یا نه. - اگر عملیات بارگیری فعالی وجود داشته باشد،
LoadStateیکLoadState.Loadingشیء است. - اگر خطایی وجود داشته باشد،
LoadStateیک شیءLoadState.Errorاست.
ازطریق ویژگی loadState در پوشاننده LazyPagingItems به این حالتها دسترسی پیدا کنید. میتوانید از این حالت به دو روش استفاده کنید: مدیریت
نمایان بودن محتوای اصلی (مانند نشانگر چرخان بازآوری تمامصفحه) یا درج
موارد درحال بارگیری مستقیماً در جریان LazyColumn (مانند نشانگر چرخان پانویس).
دسترسی به وضعیت بارگیری با شنونده
برای پایش وضعیت بارگیری در واسط کاربر، از ویژگی loadState
ارائهشده توسط پوشاننده LazyPagingItems استفاده کنید. این کار شیء
CombinedLoadStates را برمیگرداند که به شما امکان میدهد به رفتار بار کردن برای
رویدادهای بازآوری، افزودن، یا پیشافزودن واکنش نشان دهید.
در مثال زیر، میانای کاربری بسته به وضعیت فعلی بارگیری بازآوری (اولیه)، گردونه بارگیری یا پیام خطا نمایش میدهد:
@Composable fun UserListScreen(viewModel: UserViewModel) { val pagingItems = viewModel.flow.collectAsLazyPagingItems() Box(modifier = Modifier.fillMaxSize()) { // Show the list content LazyColumn { items(pagingItems.itemCount) { index -> UserItem(pagingItems[index]) } } // Handle the loading state when (val state = pagingItems.loadState.refresh) { is LoadState.Loading -> { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } is LoadState.Error -> { ErrorButton( message = state.error.message ?: "Unknown error", onClick = { pagingItems.retry() }, modifier = Modifier.align(Alignment.Center) ) } else -> {} // No separate view needed for success/not loading } } }
برای اطلاعات بیشتر درباره LazyPagingItems، مجموعه دادههای بزرگ (صفحهبندی) را ببینید.
افزودن سرصفحه و پاصفحه بارگیری
برای نمایش نشانگرهای بارگیری در ابتدا یا انتهای فهرست (بهعنوان سرصفحه یا پاصفحه)، بلوکهای اختصاصی برای آن حالتها در محدوده LazyColumn اضافه کنید.
میتوانید وضعیت پیشافزودن را برای سرصفحه و وضعیت پسافزودن را برای پاصفحه بااستفاده از شیء CombinedLoadStates پایش کنید.
در مثال زیر، وقتی دادههای بیشتری واکشی میشود، فهرست یک نوار پیشرفت یا دکمه امتحان مجدد را در پایین فهرست نمایش میدهد:
@Composable fun UserList(viewModel: UserViewModel) { val pagingItems = viewModel.pager.flow.collectAsLazyPagingItems() LazyColumn { // 1. Header (Prepend state) // Useful if you support bidirectional paging or jumping to the middle item { val prependState = pagingItems.loadState.prepend if (prependState is LoadState.Loading) { LoadingItem() } else if (prependState is LoadState.Error) { ErrorItem( message = prependState.error.message ?: "Error", onClick = { pagingItems.retry() } ) } } // 2. Main Data items(pagingItems.itemCount) { index -> UserItem(pagingItems[index]) } // 3. Footer (Append state) // Shows when the user scrolls to the bottom and more data is loading item { val appendState = pagingItems.loadState.append if (appendState is LoadState.Loading) { LoadingItem() } else if (appendState is LoadState.Error) { ErrorItem( message = appendState.error.message ?: "Error", onClick = { pagingItems.retry() } ) } } } } @Composable fun LoadingItem() { Box(modifier = Modifier.fillMaxWidth().padding(16.dp), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } @Composable fun ErrorItem(message: String, onClick: () -> Unit) { Column( modifier = Modifier.fillMaxWidth().padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = message, color = Color.Red) Button(onClick = onClick) { Text("Retry") } } }
دسترسی به اطلاعات بیشتر درباره وضعیت بارگیری
همانطور که در مثالهای قبلی نشان داده شد، تماس گرفتن با pagingItems.loadState.refresh
راحت است. بااینحال، تفاوت بین بار کردن از پایگاه داده محلی (PagingSource) و شبکه (RemoteMediator) را پنهان میکند.
این امر میتواند باعث شود که واسط کاربر برای مدت کوتاهی یک نشانگر بارگیری را نشان دهد، حتی زمانی که دادههای ذخیرهشده در حافظه نهان بلافاصله دردسترس هستند.
برای کنترل دقیق، مثل نشان دادن نشانگر بارگیری فقط وقتی که پایگاه داده محلی
خالی است و همگامسازی شبکه فعال است، مستقیماً در composable خود به ویژگیهای source و mediator
دسترسی پیدا کنید.
val loadState = pagingItems.loadState val isSyncing = loadState.mediator?.refresh is LoadState.Loading val isLocalEmpty = loadState.source.refresh is LoadState.NotLoading && pagingItems.itemSnapshotList.items.isEmpty() if (isSyncing && isLocalEmpty) { FullScreenLoading() } else { UserList(pagingItems) if (isSyncing) { TopOverlaySpinner() } }
چون pagingItems.loadState هربار که prepend یا append درطول پیمایش تغییر میکند، شیء CombinedLoadStates جدیدی منتشر میکند، بررسی بازآوری را در derivedStateOf با remember(pagingItems) بپیچید. این کار از بازترکیب کردن محدوده والد توسط بهروزرسانیهای لبه پیمایش که فقط نشانگر بازآوری تمامصفحه را تغییر وضعیت میدهد جلوگیری میکند:
val showFullScreenLoading by remember(pagingItems) { derivedStateOf { // Avoid recomposing on prepend or append updates while scrolling, and // avoid covering existing items during a background refresh. pagingItems.loadState.source.refresh is LoadState.Loading && pagingItems.itemCount == 0 } } if (showFullScreenLoading) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { CircularProgressIndicator() } }
واکنش نشان دادن به تغییرات وضعیت بارگیری
ممکن است لازم باشد عوارض جانبی یکباره را براساس تغییرات وضعیت بارگیری راهاندازی کنید،
مانند پیمایش به بالای فهرست یا نمایش Snackbar هنگام تکمیل یا عدم موفقیت بازآوری.
از snapshotFlow در LaunchedEffect استفاده کنید تا تغییرات وضعیت را بهصورت
جاریسازی مشاهده کنید. این به شما امکان میدهد تا عملگرهای استاندارد Flow مانند filter،
distinctUntilChanged، و distinctUntilChangedBy را برای جداسازی
رویدادهای خاص اعمال کنید.
val listState = rememberLazyListState() LaunchedEffect(pagingItems) { // 1. Convert the state to a Flow snapshotFlow { pagingItems.loadState.refresh } // 2. Filter for the specific event (Refresh completed successfully) .distinctUntilChanged() .filter { it is LoadState.NotLoading } .collect { // 3. Trigger the side effect listState.animateScrollToItem(0) } }
بهطور مشابه، میتوانید از distinctUntilChangedBy در loadState برای نمایش
خطای Snackbar فقط زمانی که refresh به
LoadState.Error انتقال مییابد استفاده کنید:
val snackbarHostState = remember { SnackbarHostState() } // Key on pagingItems rather than loadState so state updates do not restart the // coroutine and reset distinctUntilChangedBy. LaunchedEffect(pagingItems) { snapshotFlow { pagingItems.loadState } // Ignore prepend and append updates so scrolling does not re-trigger the // refresh error Snackbar. .distinctUntilChangedBy { it.refresh } .filter { it.refresh is LoadState.Error } .collect { loadState -> val error = (loadState.refresh as LoadState.Error).error val result = snackbarHostState.showSnackbar( message = "Data failed to load: ${error.localizedMessage ?: "Unknown error"}", actionLabel = "Retry" ) if (result == SnackbarResult.ActionPerformed) { pagingItems.retry() } } }
منابع بیشتر
برای اطلاعات بیشتر درباره کتابخانه «صفحهبندی» و وضعیتهای بارگیری، به منابع زیر مراجعه کنید.
اسناد
محتوا را مشاهده میکند
توصیهشده برای شما
- توجه: وقتی جاوا اسکریپت خاموش باشد، نوشتار پیوند نمایش داده میشود
- نمای کلی کتابخانه صفحهبندی