تتتبّع مكتبة Paging حالة طلبات التحميل للبيانات المقسَّمة إلى صفحات وتعرضها
من خلال فئة LoadState.
يتم توفير إشارة LoadState منفصلة لكل
LoadType ونوع مصدر البيانات
(إما PagingSource أو
RemoteMediator). يقدّم عنصر
CombinedLoadStates
الذي يوفّره المتتبِّع معلومات عن حالة التحميل
من كل هذه الإشارات. يمكنك استخدام هذه المعلومات التفصيلية لعرض مؤشرات التحميل المناسبة للمستخدِمين.
حالات التحميل
تعرض مكتبة Paging حالة التحميل لاستخدامها في واجهة المستخدِم من خلال عنصر LoadState. تتخذ عناصر LoadState أحد الأشكال الثلاثة التالية استنادًا إلى حالة التحميل الحالية:
- إذا لم تكن هناك عملية تحميل نشطة ولم يحدث أي خطأ، يكون
LoadStateعنصرLoadState.NotLoading. يتضمّن هذا الفئة الفرعية أيضًا السمةendOfPaginationReachedالتي تشير إلى ما إذا تم الوصول إلى نهاية الترقيم. - إذا كانت هناك عملية تحميل نشطة، يكون
LoadStateعنصرLoadState.Loading. - إذا حدث خطأ، يكون
LoadStateعنصرLoadState.Error.
يمكنك الوصول إلى هذه الحالات من خلال السمة loadState لغلاف
LazyPagingItems. يمكنك استخدام هذه الحالة بطريقتَين: معالجة مدى ظهور المحتوى الرئيسي (مثل مؤشر سريان العمل الخاص بتحديث ملء الشاشة) أو إدراج عناصر التحميل مباشرةً في مصدر بيانات LazyColumn (مثل مؤشر سريان العمل الخاص بالتذييل).
الوصول إلى حالة التحميل باستخدام مستمع
لمراقبة حالة التحميل في واجهة المستخدِم، استخدِم السمة loadStateproperty
التي يوفّرها غلاف 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). ويمكن أن يؤدي ذلك إلى أن تعرض واجهة المستخدِم مؤشر سريان عمل خاصًا بالتحميل لفترة وجيزة حتى عندما تكون البيانات المخزّنة مؤقتًا متاحة على الفور.
للحصول على تحكّم دقيق، مثل عرض مؤشر سريان عمل خاص بالتحميل فقط عندما تكون قاعدة البيانات المحلية فارغة ويكون مزامنة الشبكة نشطة، يمكنك الوصول إلى سمتَي 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() } }
التفاعل مع تغييرات حالة التحميل
قد تحتاج إلى تشغيل آثار جانبية لمرة واحدة استنادًا إلى تغييرات حالة التحميل، مثل الانتقال إلى أعلى القائمة أو عرض Snackbar عند اكتمال التحديث.
استخدِم snapshotFlow داخل LaunchedEffect لمراقبة تغييرات الحالة كمصدر بيانات. يتيح لك ذلك تطبيق عوامل تشغيل Flow العادية، مثل filter
و distinctUntilChanged لعزل أحداث معيّنة.
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) } }
مراجع إضافية
لمزيد من المعلومات عن مكتبة Paging وحالات التحميل، يُرجى الاطّلاع على المراجع التالية.
الوثائق
Content Views
مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما يكون JavaScript غير مفعّل
- نظرة عامة على مكتبة Paging