pagist 0.0.1 copy "pagist: ^0.0.1" to clipboard
pagist: ^0.0.1 copied to clipboard

A modern Flutter pagination package that provides efficient data loading with customizable UI components for lists and grids.

Pagist πŸ“„ #

pub package CI codecov style: very good analysis License: MIT Flutter

A modern, efficient, and state-management agnostic pagination library for Flutter applications. Pagist provides a clean abstraction for handling paginated data with automatic loading, error handling, and refresh capabilities.

✨ Features #

  • πŸ”„ Automatic pagination: Seamlessly loads more data as users scroll
  • πŸ”„ Pull-to-refresh: Built-in refresh functionality
  • 🎯 State management agnostic: Works with any state management solution
  • πŸ›‘οΈ Type-safe: Full TypeScript-like generics support
  • 🎨 Customizable UI: Flexible widget customization for all states
  • ⚑ Performance optimized: Efficient memory usage and smooth scrolling
  • πŸ§ͺ Well tested: Comprehensive test coverage
  • πŸ“± Production ready: Battle-tested in real applications

πŸš€ Getting Started #

Installation #

Add pagist to your pubspec.yaml:

dependencies:
  pagist: ^0.0.1

Then run:

flutter pub get

Import #

import 'package:pagist/pagist.dart';

πŸ“– Usage #

Basic Example #

Here's a simple example showing how to implement pagination for a list of users:

import 'package:flutter/material.dart';
import 'package:pagist/pagist.dart';

// 1. Define your data model
class User {
  final int id;
  final String name;
  final String email;

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

// 2. Implement PagingSource
class UserPagingSource extends PagingSource<int, User> {
  @override
  Future<LoadResult<int, User>> load(LoadParams<int> params) async {
    final page = params.key ?? 1;
    final users = await fetchUsersFromApi(page, params.loadSize);
    
    return LoadResult<int, User>(
      data: users,
      nextKey: users.isNotEmpty ? page + 1 : null,
    );
  }
  
  Future<List<User>> fetchUsersFromApi(int page, int pageSize) async {
    // Your API call implementation
    // ...
  }
}

// 3. Use in your widget
class UserListPage extends StatefulWidget {
  @override
  _UserListPageState createState() => _UserListPageState();
}

class _UserListPageState extends State<UserListPage> {
  late PaginationController<int, User> _controller;

  @override
  void initState() {
    super.initState();
    _controller = PaginationController<int, User>(
      pagingSource: UserPagingSource(),
      pageSize: 20,
      initialKey: 1,
    );
    _controller.loadMore(); // Load initial data
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Users')),
      body: PaginatedListView<User>(
        controller: _controller,
        itemBuilder: (context, user, index) {
          return ListTile(
            title: Text(user.name),
            subtitle: Text(user.email),
          );
        },
      ),
    );
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

Advanced Customization #

PaginatedListView<User>(
  controller: _controller,
  enableRefresh: true,
  loadMoreThreshold: 200.0, // Load more when 200px from bottom
  itemBuilder: (context, user, index) {
    return UserCard(user: user);
  },
  loadingWidget: Center(
    child: CircularProgressIndicator(),
  ),
  errorWidget: ErrorRetryWidget(
    onRetry: () => _controller.refresh(),
  ),
  emptyWidget: EmptyStateWidget(),
  loadingMoreWidget: Padding(
    padding: EdgeInsets.all(16),
    child: Center(child: CircularProgressIndicator()),
  ),
)

Using with State Management #

Pagist works seamlessly with any state management solution. Here's an example with Provider:

class UserListNotifier extends ChangeNotifier {
  late PaginationController<int, User> _controller;
  
  UserListNotifier() {
    _controller = PaginationController<int, User>(
      pagingSource: UserPagingSource(),
      pageSize: 20,
    );
    
    // Listen to pagination state changes
    _controller.stateStream.listen((_) => notifyListeners());
  }
  
  PaginationState<User> get state => _controller.currentState;
  
  void loadMore() => _controller.loadMore();
  void refresh() => _controller.refresh();
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

πŸ—οΈ Architecture #

Pagist follows a clean architecture pattern with clear separation of concerns:

Core Components #

  • PagingSource<Key, Value>: Abstract class defining how to load data
  • PaginationController<Key, Value>: Manages pagination state and loading logic
  • PaginatedListView<T>: Flutter widget that displays paginated data
  • LoadParams<Key>: Parameters passed to the paging source
  • LoadResult<Key, Value>: Result returned by the paging source
  • PaginationState<Value>: Current state of pagination

Flow Diagram #

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  PagingSource   │◄───│PaginationController│◄───│PaginatedListViewβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                       β”‚                       β”‚
         β”‚                       β”‚                       β”‚
         β–Ό                       β–Ό                       β–Ό
    Load Data              Manage State            Display UI

πŸ”§ API Reference #

PagingSource #

abstract class PagingSource<Key, Value> {
  Future<LoadResult<Key, Value>> load(LoadParams<Key> params);
}

PaginationController #

class PaginationController<Key, Value> {
  PaginationController({
    required PagingSource<Key, Value> pagingSource,
    int pageSize = 20,
    Key? initialKey,
  });
  
  Stream<PaginationState<Value>> get stateStream;
  PaginationState<Value> get currentState;
  
  Future<void> loadMore();
  Future<void> refresh();
  void dispose();
}

PaginatedListView #

class PaginatedListView<T> extends StatefulWidget {
  const PaginatedListView({
    required this.controller,
    required this.itemBuilder,
    this.loadingWidget,
    this.errorWidget,
    this.emptyWidget,
    this.loadingMoreWidget,
    this.loadMoreThreshold = 200.0,
    this.enableRefresh = true,
  });
}

πŸ§ͺ Testing #

Pagist is designed to be easily testable. Here's how to test your pagination logic:

void main() {
  group('UserPagingSource', () {
    late UserPagingSource pagingSource;
    
    setUp(() {
      pagingSource = UserPagingSource();
    });
    
    test('should load first page correctly', () async {
      final result = await pagingSource.load(
        LoadParams<int>(key: 1, loadSize: 10),
      );
      
      expect(result.data.length, 10);
      expect(result.nextKey, 2);
    });
  });
}

🀝 Contributing #

We welcome contributions! Please see our Contributing Guide for details.

Development Setup #

  1. Fork the repository
  2. Clone your fork: git clone https://github.com/yourusername/pagist.git
  3. Install dependencies: flutter pub get
  4. Run tests: flutter test
  5. Create a branch: git checkout -b feature/your-feature
  6. Make your changes and add tests
  7. Run tests: flutter test
  8. Submit a pull request

πŸ“ License #

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

πŸ™‹β€β™‚οΈ Support #

🌟 Show your support #

Give a ⭐️ if this project helped you!

1
likes
140
points
6
downloads

Publisher

unverified uploader

Weekly Downloads

A modern Flutter pagination package that provides efficient data loading with customizable UI components for lists and grids.

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on pagist