So I'm trying to build a GridView.builder with pagination in Flutter to display a list of items, but I'm only able to display the 10 first items. I can see when I print the response.body that the next items are fetched when I reach the bottom, but I only get the circularIndicator and the next 10 items are not displayed.
What I have tried:
I followed this tutorial from the bloc team
https://bloclibrary.dev/#/flutterinfinitelisttutorial?id=post-events
Here the code for my Bloc:
const throttleDuration = Duration(seconds: 1);
EventTransformer<E> throttleDroppable<E>(Duration duration) {
return (events, mapper) {
return droppable<E>().call(events.throttle(duration), mapper);
};
}
class NgoItemListBloc extends Bloc<NgoItemListEvent, NgoItemListState> {
final BackendAPI backendAPI;
NgoItemListBloc(this.backendAPI) : super(const NgoItemListState()) {
on<LoadNgoItemList>(
_onLoadNgoItemList,
transformer: throttleDroppable(throttleDuration),
);
}
Future<void> _onLoadNgoItemList(LoadNgoItemList event, Emitter<NgoItemListState> emit) async {
if (state.hasReachedMax) return;
try {
if (state.status == ItemsStatus.initial) {
final items = await backendAPI.fetchNgoItems(event.ngoId);
return emit(state.copyWith(
status: ItemsStatus.success,
ngoItems: items,
hasReachedMax: false,
));
}
final items = await backendAPI.fetchNgoItems(event.ngoId,state.ngoItems.length);
emit(items.isEmpty
? state.copyWith(hasReachedMax: true)
: state.copyWith(
status: ItemsStatus.success,
ngoItems: List.of(state.ngoItems)..addAll(items),
hasReachedMax: false,
));
} catch (_) {
emit(state.copyWith(status: ItemsStatus.failure));
}
}
}
Here the code for my BlocProvider:
BlocProvider<NgoItemListBloc>(
create: (context) => bloc
..add(
LoadNgoItemList(ngo.id),
),
child: BlocBuilder<NgoItemListBloc, NgoItemListState>(
builder: (context, state) {
items = state.ngoItems;
switch (state.status) {
case ItemsStatus.failure:
return const Center(
child: Text('error to load!'),
);
case ItemsStatus.success:
if (items.isEmpty) {
return const Center(
child: Text('no items available!'),
);
}
return Container(
color: Colors.white,
child: GridView.builder(
controller: _scrollController,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: crossAxisSpacing,
childAspectRatio: aspectRatio,
crossAxisCount: crossAxisCount,
),
itemCount: state.hasReachedMax ? items.length : items.length + 1,
itemBuilder: (BuildContext context, int index) {
return index >= items.length
? const MyCircularProgressIndicator()
: _ItemListView(
onTap: _handleItemTapped,
item: items[index],
ngoName: ngo.name,
);
},
),
);
default:
return const Center(
child: MyCircularProgressIndicator(),
);
}
},
),
),
and I think the problem is coming from the _onScroll function but I'm not really sure.
void _onScroll() {
if (_isBottom) {
BlocProvider.of<NgoItemListBloc>(context)
.add(LoadNgoItemList(ngo.id));
}
}
API call:
Future<List<Item>> fetchNgoItems(int ngoId, [int startIndex = 0]) async {
final http.Response response =
await _httpClient.get("/ngo/$ngoId/item?page=$startIndex&size=$maxItemsPerPage");
print(response.body);
return jsonDecode(utf8.decode(response.bodyBytes))['content']
.map<Item>((json) => Item.fromJson(json))
.toList();
}
Thank you in advance for your help!