When working with a list of data, there is a chance that you can have hundreds or even thousands of data. This is going to be the case especially if the data is being fetched remotely from a Web service or from cloud storage like Firebase. What then do you do in that case? Do you just download all that data at once, utilizing users bandwidth? Even if you do so will then just cram all that data in memory, making the app slow and heavy?And then from the User experience perspective, will your users not be overwhelmed by hundreds or thousands of rows of data?
In short it isn't a good approach to download alot of data at once. It consumes users precious bandwidth while making the app slow. The solution is to paginate data. Paginating or Paging data means data is loaded in chunks on demand. Users can interact with only a limited data set then more data can be loaded as the user scrolls.
There are various pagination techniques. In the mobile development arena the most commonly used technique is the load more pagination. Through this technique data is loaded as the user scrolls the listview.
In this piece we want to look at some projects or libaries to help us implement this technique. Our framework is Flutter of course.
Example 1 - Load more Pagination in ListView using the loadMore library.
This libary makes it very easy to implement the load more pagination in a listview. It supports only ListView.
The first step is to install it:
dependencies:
loadmore: [latest_version]
You can find the latest version here.
(a). listview.dart
Then create a dart file called listview.dart
.
In that file start by adding imports:
import 'package:flutter/material.dart';
Then create a StatefulWidget to represent the demo page:
class ListViewDemoPage extends StatefulWidget {
@override
_ListViewDemoPageState createState() => _ListViewDemoPageState();
}
In the above the createState()
method has been overriden and you can see a custom private class is being returned called _ListViewDemoPageState
.
Now come and create that file making it extend the State class:
class _ListViewDemoPageState extends State<ListViewDemoPage> {
Now define in that a state class an instance field:
var count = 10;
Then override the buld items and increment the count variable by 1 in the ListView builder and assign the count to itemCount property of the listview:
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: count + 1,
itemBuilder: _buildItem,
);
}
Here is the definition of that _buildItem
method:
Widget _buildItem(BuildContext context, int index) {
if (index == count) {
return Text('到底了');
}
return Text(index.toString());
}
Here is the full class:
import 'package:flutter/material.dart';
class ListViewDemoPage extends StatefulWidget {
@override
_ListViewDemoPageState createState() => _ListViewDemoPageState();
}
class _ListViewDemoPageState extends State<ListViewDemoPage> {
var count = 10;
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: count + 1,
itemBuilder: _buildItem,
);
}
Widget _buildItem(BuildContext context, int index) {
if (index == count) {
return Text('到底了');
}
return Text(index.toString());
}
}
(b). main.dart
In the main class come and add imports including the installed loadmore flutter plugin:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:loadmore/loadmore.dart';
Create the MyApp
class by extending the StatelessWidget class:
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
Now come create a statefulwidget class representing the homepage:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
You now need to define the state for that class given that it's a stateful widget class:
class _MyHomePageState extends State<MyHomePage> {
In it define an instance field and a method representing the list of items as well as their count respectively:
int get count => list.length;
List<int> list = [];
Define the load()
method:
void load() {
print("load");
setState(() {
list.addAll(List.generate(15, (v) => v));
print("data count = ${list.length}");
});
}
The list is being populated in the above method with numbers.
Now come define an asynchronous load more and refresh functions:
Future<bool> _loadMore() async {
print("onLoadMore");
await Future.delayed(Duration(seconds: 0, milliseconds: 2000));
load();
return true;
}
Future<void> _refresh() async {
await Future.delayed(Duration(seconds: 0, milliseconds: 2000));
list.clear();
load();
}
Then override the build()
method:
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: Container(
child: RefreshIndicator(
child: LoadMore(
isFinish: count >= 60,
onLoadMore: _loadMore,
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Container(
child: Text(list[index].toString()),
height: 40.0,
alignment: Alignment.center,
);
},
itemCount: count,
),
whenEmptyLoad: false,
delegate: DefaultLoadMoreDelegate(),
textBuilder: DefaultLoadMoreTextBuilder.chinese,
),
onRefresh: _refresh,
),
),
);
}
Here is the demo:
Flutter LoadMore Pagination
Special thanks to @CaiJingLong for this project and libary.