riverpod_pagination 0.1.0 copy "riverpod_pagination: ^0.1.0" to clipboard
riverpod_pagination: ^0.1.0 copied to clipboard

A simple and effective pagination solution for Flutter apps using Riverpod state management.

riverpod_pagination #

A simple and effective pagination solution for Flutter apps using Riverpod state management.

pub package License: MIT

Features #

  • πŸš€ Multiple pagination strategies: Token-based, offset-based, and page number-based pagination
  • 🎯 Easy to use: Simple API with sensible defaults
  • πŸ”§ Highly customizable: Customize loading states, error handling, and UI components
  • πŸ“± ListView and GridView support: Built-in widgets for both list and grid layouts
  • ♻️ Automatic retry logic: Built-in error handling with configurable retry attempts
  • 🎨 Material Design 3: Modern default widgets following Material Design guidelines
  • πŸ”„ Pull-to-refresh: Built-in refresh functionality
  • ⚑ Performance optimized: Efficient scroll detection and state management

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  riverpod_pagination: ^0.1.0
  flutter_riverpod: ^2.4.0

Quick Start #

1. Create your data model #

class User {
  final int id;
  final String name;
  final String email;

  const User({required this.id, required this.name, required this.email});
}

2. Extend PaginatedNotifier #

class UsersNotifier extends PaginatedNotifier<User> {
  final ApiService _apiService = ApiService();

  UsersNotifier() : super(
    config: const PaginationConfig(pageSize: 20),
    strategy: PaginationStrategy.token,
  );

  @override
  Future<PaginationResult<User>> fetchPage(PaginationParams params) async {
    if (params is TokenPaginationParams) {
      return await _apiService.getUsers(
        nextPageToken: params.nextPageToken,
        limit: params.limit,
      );
    }
    throw ArgumentError('Invalid pagination params');
  }
}

3. Create your provider #

final usersProvider = StateNotifierProvider<UsersNotifier, DefaultPaginatedState<User>>(
  (ref) => UsersNotifier(),
);

4. Use PaginatedListView in your widget #

class UsersScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final notifier = ref.read(usersProvider.notifier);

    return Scaffold(
      body: PaginatedListView<User, DefaultPaginatedState<User>>(
        provider: usersProvider,
        itemBuilder: (context, user, index) => ListTile(
          title: Text(user.name),
          subtitle: Text(user.email),
        ),
        onLoad: () => notifier.loadFirstPage(),
        onLoadMore: (token) => notifier.loadMore(),
        onRefresh: () => notifier.refresh(),
      ),
    );
  }
}

Pagination Strategies #

Token-based Pagination (Cursor-based) #

Best for APIs that return a next page token or cursor:

class TokenNotifier extends PaginatedNotifier<Item> {
  TokenNotifier() : super(strategy: PaginationStrategy.token);

  @override
  Future<PaginationResult<Item>> fetchPage(PaginationParams params) async {
    final tokenParams = params as TokenPaginationParams;
    return await api.getItems(
      nextPageToken: tokenParams.nextPageToken,
      limit: tokenParams.limit,
    );
  }
}

Offset-based Pagination #

Best for APIs that use skip/take or offset/limit parameters:

class OffsetNotifier extends PaginatedNotifier<Item> {
  OffsetNotifier() : super(strategy: PaginationStrategy.offset);

  @override
  Future<PaginationResult<Item>> fetchPage(PaginationParams params) async {
    final offsetParams = params as OffsetPaginationParams;
    return await api.getItems(
      offset: offsetParams.offset,
      limit: offsetParams.limit,
    );
  }
}

Page Number-based Pagination #

Best for APIs that use page numbers:

class PageNotifier extends PaginatedNotifier<Item> {
  PageNotifier() : super(strategy: PaginationStrategy.pageNumber);

  @override
  Future<PaginationResult<Item>> fetchPage(PaginationParams params) async {
    final pageParams = params as PageNumberPaginationParams;
    return await api.getItems(
      page: pageParams.page,
      pageSize: pageParams.pageSize,
    );
  }
}

Grid View Support #

Use PaginatedGridView for grid layouts:

PaginatedGridView<Photo, DefaultPaginatedState<Photo>>.count(
  provider: photosProvider,
  crossAxisCount: 2,
  itemBuilder: (context, photo, index) => PhotoCard(photo: photo),
  onLoad: () => notifier.loadFirstPage(),
  onLoadMore: (token) => notifier.loadMore(),
  onRefresh: () => notifier.refresh(),
)

Configuration Options #

Customize pagination behavior with PaginationConfig:

PaginatedNotifier(
  config: const PaginationConfig(
    pageSize: 30,                    // Items per page
    scrollThreshold: 0.8,            // When to trigger load more (80% scrolled)
    autoLoad: true,                  // Auto-load first page
    maxRetries: 3,                   // Retry failed requests
    retryDelay: Duration(seconds: 1), // Delay between retries
  ),
  strategy: PaginationStrategy.token,
)

Custom Widgets #

Customize loading states and error handling:

PaginatedListView(
  provider: itemsProvider,
  itemBuilder: (context, item, index) => ItemCard(item: item),
  loadingWidget: CustomLoadingWidget(),
  errorWidget: (error, retry) => CustomErrorWidget(
    error: error,
    onRetry: retry,
  ),
  emptyWidget: CustomEmptyWidget(),
  loadingMoreWidget: CustomLoadingMoreWidget(),
  // ... other callbacks
)

Advanced Usage #

Custom State Management #

Implement your own state class:

class CustomPaginatedState implements PaginatedState<Item> {
  // Implement required methods
  @override
  final List<Item> items;
  
  @override
  final bool isLoading;
  
  // ... other required properties
}

Error Handling #

Handle specific errors in your notifier:

@override
Future<PaginationResult<Item>> fetchPage(PaginationParams params) async {
  try {
    return await api.getItems(params);
  } on NetworkException catch (e) {
    throw 'Network error: Please check your connection';
  } on AuthException catch (e) {
    throw 'Authentication failed: Please log in again';
  }
}

Examples #

Check out the example directory for complete working examples:

  • Users List: Token-based pagination with user profiles
  • Posts List: Offset-based pagination with article cards
  • Photos Grid: Page number-based pagination with image grid

To run the examples:

cd example
flutter run

API Reference #

PaginatedNotifier #

Base class for pagination logic.

Constructor Parameters:

  • config: Pagination configuration options
  • strategy: Pagination strategy (token, offset, or pageNumber)

Methods:

  • loadFirstPage(): Load the initial page
  • loadMore(): Load the next page
  • refresh(): Refresh from the beginning

PaginatedListView<T, S> #

Widget for paginated list views.

Required Parameters:

  • provider: Riverpod provider containing paginated state
  • itemBuilder: Function to build each list item
  • onLoad: Callback for initial load
  • onLoadMore: Callback for loading more items
  • onRefresh: Callback for refresh

PaginatedGridView<T, S> #

Widget for paginated grid views with the same API as PaginatedListView plus grid-specific options.

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

License #

This project is licensed under the MIT License - see the LICENSE file for details.

1
likes
130
points
32
downloads

Publisher

unverified uploader

Weekly Downloads

A simple and effective pagination solution for Flutter apps using Riverpod state management.

Documentation

API reference

License

MIT (license)

Dependencies

flutter, flutter_riverpod

More

Packages that depend on riverpod_pagination