Flutter infinite scrolling using riverpod

Bibek Magar
wesionaryTEAM
Published in
3 min readMar 30, 2022

--

Infinite scrolling in flutter

Infinite scrolling is a technique that loads content continuously as the user scrolls down the page which eliminates the need for pagination. Infinite scrolling is also known as infinite scrolling pagination,endless scrolling, auto pagination, progressive loading pagination and many more. Infinite scrolling is popular on different sites/apps nowadays. Websites/apps like twitter, reddit, facebook and many other use the infinite scrolling.
Okay lets begin infinite scrolling implementation in flutter.

Okay, lets begin with MODEL. To simplify the project I have created simple model Room which contains id and data as ‘string’.

class Room with _$Room {
const Room._();
factory Room({
@JsonKey(name: 'id') required String id,
@JsonKey(name: 'data') required String data,
}) = _Room;
factory Room.fromJson(Map<String, dynamic> json) => _$RoomFromJson(json);
}

And for collection of room we will be creating another MODEL data list state which contains list of Room.

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:my_app/model/room.dart';
part 'data_list.state.freezed.dart';@freezed
class DataListState with _$DataListState {
const factory DataListState({
@Default([]) List<Room> rooms,
@Default(false) bool isLoading,
@Default(false) bool isFetchingNext,
@Default(true) bool hasNext,
}) = _DataListState;
}

As we can see for loader during initial load and during scrolling, we are adding isLoading and isFetchingNext. Similarly, we are adding hasNext bool to stop infinite API calls or to know no more data to load.

Now for interacting with database we are creating firebase service which helps to get data.

Future<List<Room>> getData() async {
final collection = (await FirebaseFirestore.instance
.collection('rooms')
.limit(limit)
.get())
.docs;
return processData(collection);
}

We will be creating another function that help us to get the remaining documents as we send the last document id.

Future<List<Room>> getNextData(lastDocID) async {final collection = (await FirebaseFirestore.instance
.collection('rooms')
.startAfterDocument(lastDocID)
.limit(limit)
.get())
.docs;
return processData(collection);
}

Now, the main part is here. We will be handling all data in state so we are creating notifier. First, we gonna get the data from getData() and load response data to state.

getData() async {
state = state.copyWith(isLoading: true);
final data = await _read(firebaseService).getData();
state = state.copyWith(rooms: data, isLoading: false);
}

For more data we will be also handling similarly, get data from fetchNextData() and add to the state.

fetchMore() async {
final oldData = [...state.rooms];
if (lastDocumentID == null) {
state = state.copyWith(hasNext: false);
return;
}
state = state.copyWith(isFetchingNext: true);final data = await _read(firebaseService).getNextData(
lastDocumentID!,
);
if (data.isNotEmpty) {
//Get it from config
const limit = 8;
if (data.length == limit) {
state =
state.copyWith(rooms: [...oldData, ...data], isFetchingNext: false);
} else {
state = state.copyWith(
rooms: [...oldData, ...data],
isFetchingNext: false,
hasNext: false,
);
}
} else {
state = state.copyWith(hasNext: false, isFetchingNext: false);
}
}

Now, in the UI part we will be using ListView and adding a scroll listener that help to determine the offset of the page and fetch next data accordingly.

@override
void initState() {
_listScrollController.addListener(_scrollListener);
super.initState();
}
ListView(
controller: _listScrollController,
physics: const AlwaysScrollableScrollPhysics(),
children: [
for (Room data in dataState.rooms)
Card(
color: Colors.amber,
child: Text(data.data),
),
],
),

Now, all the call part is done from _scrollListener.

void _scrollListener() {
if (listState.hasNext &&
!listState.isFetchingNext &&
_listScrollController.offset >=
_listScrollController.position.maxScrollExtent &&
!_listScrollController.position.outOfRange) {
//Fetching part from API is done from here
listNotifier.fetchMore();
}
}

And we are good to go.

Summary

Step 01: Create model for room and state.
Step 02: Create a service that help to interact with database. (fetch & fetchMore)
Step 03: Create a notifier that handle all the data into states.
Step 04: Add a UI with scroll listener and fetchMore according to offset.

For full example implementation, here is a link to the repo.
Twitter: @_bibek_ma

Thank you for reading…

--

--