Infinite Scroll in Flutter: solved pagination exercise

  2 minutes

If you are looking for infinite scroll in Flutter, this solved exercise gives you a practical implementation pattern you can reuse in real projects.

Build a screen with:

  • load initial batch of records
  • detect near-bottom scroll
  • append next page safely
import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: InfinitePage()));

class InfinitePage extends StatefulWidget {
  const InfinitePage({super.key});

  @override
  State<InfinitePage> createState() => _InfinitePageState();
}

class _InfinitePageState extends State<InfinitePage> {
  final controller = ScrollController();
  final items = <int>[];
  bool loading = false;

  @override
  void initState() {
    super.initState();
    loadMore();
    controller.addListener(() {
      if (controller.position.pixels >= controller.position.maxScrollExtent - 120 && !loading) {
        loadMore();
      }
    });
  }

  Future<void> loadMore() async {
    setState(() => loading = true);
    await Future.delayed(const Duration(milliseconds: 700));
    final start = items.length;
    items.addAll(List.generate(20, (i) => start + i + 1));
    setState(() => loading = false);
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Scroll infinito')),
      body: ListView.builder(
        controller: controller,
        itemCount: items.length + (loading ? 1 : 0),
        itemBuilder: (_, i) {
          if (i >= items.length) {
            return const Padding(
              padding: EdgeInsets.all(16),
              child: Center(child: CircularProgressIndicator()),
            );
          }
          return ListTile(title: Text('Item ${items[i]}'));
        },
      ),
    );
  }
}

The list adds new items progressively while the user keeps scrolling.

  • Firing parallel loads.
  • Forgetting to dispose ScrollController.
  • Missing prefetch threshold.

Widely used for social feeds, catalogs, activity logs, and search pages.

Use a loading guard and track end-of-list state.

Not if you load in controlled batches and avoid heavy rebuilds.

Classic pagination or a “Load more” interaction.