Skip to content

Instantly share code, notes, and snippets.

@victor-carv
Last active August 10, 2022 14:15
Show Gist options
  • Select an option

  • Save victor-carv/7badfad5cdcf3d6a4708aa2b21022d78 to your computer and use it in GitHub Desktop.

Select an option

Save victor-carv/7badfad5cdcf3d6a4708aa2b21022d78 to your computer and use it in GitHub Desktop.
flutter huge lists
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter list sample',
home: HomePage());
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// We will fetch data from this Rest api
final _baseUrl = 'https://dry-ridge-81455.herokuapp.com/properties';
int _page = 1;
final int _limit = 25;
bool _hasNextPage = true;
bool _isFirstLoadRunning = false;
bool _isLoadMoreRunning = false;
// This holds the posts fetched from the server
List _properties = [];
dynamic responseData;
// This function will be called when the app launches (see the initState function)
void _firstLoad() async {
print('Start');
setState(() {
_isFirstLoadRunning = true;
});
try {
final res =
await http.get(Uri.parse("$_baseUrl?page=$_page&offset=$_limit"));
setState(() {
responseData = json.decode(res.body);
_properties = responseData['data'];
});
} catch (err) {
if (kDebugMode) {
print('Something went wrong');
}
}
setState(() {
_isFirstLoadRunning = false;
});
}
// This function will be triggered whenver the user scroll
// to near the bottom of the list view
void _loadMore() async {
if (_hasNextPage == true &&
_isFirstLoadRunning == false &&
_isLoadMoreRunning == false &&
_controller.position.extentAfter < 300) {
print('Load more');
setState(() {
_isLoadMoreRunning = true; // Display a progress indicator at the bottom
});
_page += 1; // Increase _page by 1
try {
final res =
await http.get(Uri.parse("$_baseUrl?page=$_page&offset=$_limit"));
dynamic newResponseData = json.decode(res.body);
final List fetchedProperties = newResponseData['data'];
if (fetchedProperties.isNotEmpty) {
setState(() {
responseData = newResponseData;
_properties.addAll(fetchedProperties);
});
} else {
// This means there is no more data
// and therefore, we will not send another GET request
setState(() {
_hasNextPage = false;
});
}
} catch (err) {
if (kDebugMode) {
print('Something went wrong!');
}
}
setState(() {
_isLoadMoreRunning = false;
});
} else {
print('NOT Load more');
}
}
// The controller for the ListView
late ScrollController _controller;
@override
void initState() {
super.initState();
_firstLoad();
_controller = ScrollController()..addListener(_loadMore);
}
@override
void dispose() {
_controller.removeListener(_loadMore);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page: $_page | Items per page: 25 | Total items: 1,000,000"),
),
body: _isFirstLoadRunning
? const Center(
child: CircularProgressIndicator(),
)
: Column(
children: [
Expanded(
child: ListView.builder(
controller: _controller,
itemCount: responseData != null
? responseData['total']
: _properties.length,
itemBuilder: (_, index) => Card(
child: index < _properties.length
? ListTile(
title: Text(_properties[index]['zip']),
subtitle:
Text(_properties[index]['primaryAddress']),
)
: const ListTile(
title: Text('Loading'),
subtitle:
Text('...'),
)
),
),
),
// when the _loadMore function is running
if (_isLoadMoreRunning == true)
const Padding(
padding: EdgeInsets.only(top: 10, bottom: 40),
child: Center(
child: CircularProgressIndicator(),
),
),
// When nothing else to load
if (_hasNextPage == false)
Container(
padding: const EdgeInsets.only(top: 30, bottom: 40),
color: Colors.amber,
child: const Center(
child: Text('You have fetched all of the content'),
),
),
],
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment