mo_infinite_scroll 1.0.0 copy "mo_infinite_scroll: ^1.0.0" to clipboard
mo_infinite_scroll: ^1.0.0 copied to clipboard

A simple and easy-to-use infinite scroll package for Flutter. Supports pull-to-refresh, pre-fetch before reaching the end, a Sliver variant for custom scroll views, and optional placeholder widgets fo [...]

mo_infinite_scroll #

A simple, easy-to-use infinite scroll package for Flutter with minimal required parameters, pull-to-refresh, smart pre-fetching, and full placeholder support.


Features #

  • Minimal required params — just fetcher and itemBuilder
  • 🔄 Pull-to-refresh built in (standalone variant)
  • Pre-fetch the next page before the user reaches the end
  • 🛑 Loop prevention — skips fetch when list is too short or already loading
  • 📦 Sliver variant — drop into any CustomScrollView, let the parent control refresh
  • 🎨 Placeholder widgets — loading, empty, and error states, all overridable
  • 🎛️ External controller — trigger refresh() from outside the widget

Getting started #

Add to your pubspec.yaml:

dependencies:
    mo_infinite_scroll: ^0.0.1

Usage #

Standalone list (with pull-to-refresh) #

import 'package:mo_infinite_scroll/mo_infinite_scroll.dart';

MoInfiniteScroll<Post>(
  fetcher: (page, limit) => myApi.getPosts(page: page, limit: limit),
  itemBuilder: (context, post) => PostCard(post: post),
)

With all options #

MoInfiniteScroll<Post>(
  fetcher: (page, limit) => myApi.getPosts(page: page, limit: limit),
  itemBuilder: (context, post) => PostCard(post: post),
  limit: 20,                          // items per page, passed to your API
  prefetchOffset: 3,                  // pre-fetch when 3 items from the end
  loadingPlaceholder: MyShimmer(),    // first-load skeleton
  emptyPlaceholder: MyEmptyState(),   // zero items
  errorPlaceholder: MyErrorState(),   // fetch error
  loadingMoreIndicator: MySpinner(),  // bottom-of-list spinner
  separatorBuilder: (_, __) => const Divider(),
  padding: const EdgeInsets.all(16),
)

External controller (refresh from an AppBar button) #

final _controller = MoInfiniteScrollController<Post>();

// In build():
Scaffold(
  appBar: AppBar(
    actions: [
      IconButton(
        icon: const Icon(Icons.refresh),
        onPressed: () => _controller.refresh(fetcher, limit),
      ),
    ],
  ),
  body: MoInfiniteScroll<Post>(
    controller: _controller,
    fetcher: fetcher,
    itemBuilder: (context, post) => PostCard(post: post),
  ),
)

Sliver variant (inside a CustomScrollView) #

final _controller = MoInfiniteScrollController<Post>();

RefreshIndicator(
  onRefresh: () => _controller.refresh(
    (page, limit) => myApi.getPosts(page: page, limit: limit),
    20,
  ),
  child: CustomScrollView(
    slivers: [
      const SliverAppBar(title: Text('Posts'), floating: true),
      MoInfiniteScrollSliver<Post>(
        controller: _controller,
        fetcher: (page, limit) => myApi.getPosts(page: page, limit: limit),
        itemBuilder: (context, post) => PostCard(post: post),
      ),
    ],
  ),
)

Parameters #

Shared by both widgets #

Parameter Type Required Default Description
fetcher PageFetcher<T> Called for each page. Receives (page, limit). Return [] or fewer items than limit to signal end.
itemBuilder Widget Function(context, T) Builds a single list item.
limit int 20 Items per page, forwarded to fetcher.
prefetchOffset int 3 Start pre-fetching when this many items remain.
controller MoInfiniteScrollController<T> internal External controller to call refresh() from outside.
loadingPlaceholder Widget spinner Shown during the first fetch.
emptyPlaceholder Widget inbox icon Shown when the list is empty.
errorPlaceholder Widget error icon + retry Shown on fetch error.
loadingMoreIndicator Widget spinner Shown at the bottom while loading more.
separatorBuilder Widget Function(context, index) none Optional separator between items.

MoInfiniteScroll only #

Parameter Type Default Description
padding EdgeInsetsGeometry none Padding for the internal ListView.
physics ScrollPhysics default Physics for the internal ListView.

How pre-fetching & loop prevention work #

  • The next page is fetched when the user scrolls within prefetchOffset items of the end.
  • If the current page returned fewer items than limit, hasReachedEnd is set to true and no further fetches are made.
  • Concurrent fetches are blocked — if a fetch is already in progress, new calls to fetchNextPage are ignored.
  • On error, further fetches are blocked until the user retries.

License #

MIT

2
likes
0
points
82
downloads

Publisher

unverified uploader

Weekly Downloads

A simple and easy-to-use infinite scroll package for Flutter. Supports pull-to-refresh, pre-fetch before reaching the end, a Sliver variant for custom scroll views, and optional placeholder widgets for loading, empty, and error states.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on mo_infinite_scroll