Skip to content

Commit 7257b4c

Browse files
committed
Update parse_live_list.dart
1 parent 4b4055c commit 7257b4c

1 file changed

Lines changed: 53 additions & 25 deletions

File tree

packages/flutter/lib/src/utils/parse_live_list.dart

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
part of 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart';
22

3-
4-
53
/// The type of function that builds a child widget for a ParseLiveList element.
64
typedef ChildBuilder<T extends sdk.ParseObject> = Widget Function(
75
BuildContext context, sdk.ParseLiveListElementSnapshot<T> snapshot, [int? index]);
@@ -210,7 +208,8 @@ class _ParseLiveListWidgetState<T extends sdk.ParseObject>
210208
}
211209

212210
_items.clear();
213-
_noDataNotifier.value = true;
211+
_noDataNotifier.value = true; // Assume no data initially
212+
// Set loading state visually *before* async work
214213
if (mounted) setState(() {});
215214

216215
final initialQuery = QueryBuilder<T>.copy(widget.query);
@@ -237,40 +236,46 @@ class _ParseLiveListWidgetState<T extends sdk.ParseObject>
237236
_liveList?.dispose();
238237
_liveList = liveList;
239238

239+
// --- Refactored Initial Item Handling ---
240+
final List<T> initialItems = [];
241+
final List<T> itemsToFetchAndCache = []; // Items needing background processing
242+
240243
if (liveList.size > 0) {
241244
for (int i = 0; i < liveList.size; i++) {
242245
final item = liveList.getPreLoadedAt(i);
243246
if (item != null) {
247+
initialItems.add(item); // Add preloaded item for immediate display
248+
// If offline mode is on, mark for background fetch/cache
244249
if (widget.offlineMode) {
245-
try {
246-
if (widget.lazyLoading) {
247-
await item.fetch();
248-
}
249-
await item.saveToLocalCache();
250-
} catch (e) {
251-
debugPrint('$connectivityLogPrefix Error saving initial object ${item.objectId} to cache: $e');
252-
}
250+
itemsToFetchAndCache.add(item);
253251
}
254-
_items.add(item);
255252
}
256253
}
257254
}
258255

256+
// Update the UI immediately with preloaded items
257+
_items.addAll(initialItems);
259258
_noDataNotifier.value = _items.isEmpty;
260-
261259
if (mounted) {
262260
setState(() {});
263261
}
262+
// --- End Refactored Initial Item Handling ---
264263

264+
// --- Start Background Fetching and Caching (if needed) ---
265+
if (itemsToFetchAndCache.isNotEmpty) {
266+
// Don't await this block, let it run in the background
267+
_fetchAndCacheItemsInBackground(itemsToFetchAndCache);
268+
}
269+
// --- End Background Fetching and Caching ---
270+
271+
// --- Stream Listener (remains the same) ---
265272
liveList.stream.listen((event) {
266273
T? objectToCache;
267274

268275
if (event is sdk.ParseLiveListAddEvent<sdk.ParseObject>) {
269-
final addedItem = event.object as T;
276+
final addedItem = event.object as T; // Cast needed
270277
if (mounted) {
271-
setState(() {
272-
_items.insert(event.index, addedItem);
273-
});
278+
setState(() { _items.insert(event.index, addedItem); });
274279
}
275280
objectToCache = addedItem;
276281
} else if (event is sdk.ParseLiveListDeleteEvent<sdk.ParseObject>) {
@@ -286,25 +291,27 @@ class _ParseLiveListWidgetState<T extends sdk.ParseObject>
286291
debugPrint('$connectivityLogPrefix LiveList Delete Event: Invalid index ${event.index}, list size ${_items.length}');
287292
}
288293
} else if (event is sdk.ParseLiveListUpdateEvent<sdk.ParseObject>) {
289-
final updatedItem = event.object as T;
294+
final updatedItem = event.object as T; // Cast needed
290295
if (event.index >= 0 && event.index < _items.length) {
291296
if (mounted) {
292-
setState(() {
293-
_items[event.index] = updatedItem;
294-
});
297+
setState(() { _items[event.index] = updatedItem; });
295298
}
296299
objectToCache = updatedItem;
297300
} else {
298301
debugPrint('$connectivityLogPrefix LiveList Update Event: Invalid index ${event.index}, list size ${_items.length}');
299302
}
300303
}
301304

305+
// Save updates from stream immediately (usually less performance critical than initial load)
302306
if (widget.offlineMode && objectToCache != null) {
307+
// Consider if fetch is needed for stream events too, though often they are complete
303308
objectToCache.saveToLocalCache();
304309
}
305310

306311
_noDataNotifier.value = _items.isEmpty;
307312
});
313+
// --- End Stream Listener ---
314+
308315
} catch (e) {
309316
debugPrint('$connectivityLogPrefix Error loading data: $e');
310317
_noDataNotifier.value = _items.isEmpty;
@@ -314,6 +321,30 @@ class _ParseLiveListWidgetState<T extends sdk.ParseObject>
314321
}
315322
}
316323

324+
// --- Helper for Background Caching ---
325+
Future<void> _fetchAndCacheItemsInBackground(List<T> items) async {
326+
debugPrint('$connectivityLogPrefix Starting background fetch/cache for ${items.length} items...');
327+
for (final item in items) {
328+
try {
329+
// Check if still mounted within the loop if operations are long
330+
if (!mounted) return;
331+
332+
// Fetch *only* if lazy loading is enabled to ensure cached data is complete
333+
if (widget.lazyLoading) {
334+
// Fetch the full object data before saving to cache when lazy loading.
335+
// We assume that if lazy loading is on, the initial object might be incomplete.
336+
await item.fetch();
337+
}
338+
await item.saveToLocalCache();
339+
} catch (e) {
340+
// Log error but continue with the next item
341+
debugPrint('$connectivityLogPrefix Error background saving object ${item.objectId} to cache: $e');
342+
}
343+
}
344+
debugPrint('$connectivityLogPrefix Finished background fetch/cache.');
345+
}
346+
// --- End Helper ---
347+
317348
Future<void> _loadMoreData() async {
318349
if (isOffline) {
319350
debugPrint('$connectivityLogPrefix Cannot load more data while offline.');
@@ -354,7 +385,6 @@ class _ParseLiveListWidgetState<T extends sdk.ParseObject>
354385
}
355386

356387
if (widget.offlineMode) {
357-
debugPrint('$connectivityLogPrefix Saving ${results.length} more items to cache...');
358388
for (final item in results) {
359389
try {
360390
if (widget.lazyLoading) {
@@ -391,7 +421,7 @@ class _ParseLiveListWidgetState<T extends sdk.ParseObject>
391421
return;
392422
}
393423
final scrollController = widget.scrollController ?? _scrollController;
394-
if (!scrollController.hasClients || scrollController.position.maxScrollExtent == null) {
424+
if (!scrollController.hasClients) {
395425
return;
396426
}
397427
final offset = scrollController.position.maxScrollExtent - scrollController.position.pixels;
@@ -570,7 +600,6 @@ class _ParseLiveListElementWidgetState<T extends sdk.ParseObject>
570600
@override
571601
void initState() {
572602
super.initState();
573-
debugPrint('ElementWidget ${widget.index}: initState');
574603
_snapshot = sdk.ParseLiveListElementSnapshot<T>(
575604
loadedData: widget.loadedData?.call(),
576605
preLoadedData: widget.preLoadedData?.call(),
@@ -605,7 +634,6 @@ class _ParseLiveListElementWidgetState<T extends sdk.ParseObject>
605634

606635
@override
607636
Widget build(BuildContext context) {
608-
debugPrint('ElementWidget ${widget.index}: build');
609637
return SizeTransition(
610638
sizeFactor: widget.sizeFactor,
611639
child: widget.index != null

0 commit comments

Comments
 (0)