Flutter分页管理插件pagination_manager的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter分页管理插件pagination_manager的使用

📦 Pagination Manager

Pub Version License: MIT

这是一个强大且灵活的Flutter包,用于处理带有内置状态管理支持的分页数据。可以轻松实现无限滚动列表,同时减少样板代码。

✨ 特性

  • 🚀 简单易用的分页管理
  • 💪 内置Bloc/Cubit状态管理支持
  • 🎯 框架无关 - 适用于任何状态管理解决方案
  • 🔄 下拉刷新支持
  • ⚡ 带有自动状态管理的懒加载
  • 🎨 可定制的加载和错误状态
  • 📱 响应式和自适应设计

📋 安装

在你的pubspec.yaml中添加以下依赖:

dependencies:
  pagination_manager: ^1.0.0

然后导入:

import 'package:pagination_manager/pagination_manager.dart';

🚀 快速开始

1. 创建一个Repository

首先,实现PaginatedRepository接口:

class MyDataRepository implements PaginatedRepository<MyData> {
  @override
  Future<PaginationResult<MyData>> fetchPaginatedItems(int page, int limitPerPage) async {
    try {
      final response = await api.fetchData(page: page, limit: limitPerPage);
      return PaginationResult.success(response);
    } catch (e) {
      return PaginationResult.failure(e.toString());
    }
  }
}

2. 初始化PaginationManager

final paginationManager = PaginationManager<MyData>(
  repository: MyDataRepository(),
  limitPerPage: 20,
);

3. 使用PaginatedManagerList(推荐)

最简单的方式是使用PaginatedManagerList来实现带有完整状态管理的分页:

PaginatedManagerList<MyData>(
  paginationManager: paginationManager,
  itemBuilder: (context, index, items) {
    final item = items[index];
    return ListTile(
      title: Text(item.title),
    );
  },
);

这将自动处理:

  • 自动无限滚动
  • 加载状态
  • 错误处理与可自定义的重试按钮
  • 下拉刷新
  • 重试机制
  • 空状态处理
自定义PaginatedManagerList
PaginatedManagerList<MyData>(
  paginationManager: paginationManager,
  itemBuilder: (context, index, items) => MyItemWidget(item: items[index]),
  // Customization options
  scrollThreshold: 0.8,                    // 在80%滚动时触发分页
  showRefreshIndicator: true,              // 启用下拉刷新
  showRetryButton: true,                   // 显示错误时的重试按钮
  emptyItemsText: 'No items found',        // 自定义空状态消息
  retryText: 'Try Again',                  // 自定义重试按钮文本
  scrollDirection: Axis.vertical,          // 滚动方向
  initialLoadingWidget: MyLoadingWidget(), // 自定义初始加载小部件
  loadingPaginationWidget: MyLoadingIndicator(), // 自定义分页加载指示器
  emptyItemsWidget: MyEmptyState(),        // 自定义空状态小部件
  whenErrMessageFromPagination: (message) {
    // 处理分页错误
    showSnackBar(message);
  },
  fetchItemsFailureWidget: (errorMessage) {
    // 自定义错误小部件
    return MyErrorWidget(message: errorMessage);
  },
  // 样式设置
  errorTextStyle: TextStyle(color: Colors.red),
  retryTextStyle: TextStyle(color: Colors.blue),
  retryButtonStyle: ButtonStyle(...),
);

4. 替代方案:手动实现

如果你需要更多控制,可以直接使用PaginatedList小部件:

PaginatedList<MyData>(
  paginationManager: paginationManager,
  loadingFromPaginationState: false,
  fetchNextPage: () => paginationManager.fetchNextPage(),
  itemBuilder: (context, index, items) {
    final item = items[index];
    return ListTile(
      title: Text(item.title),
    );
  },
  retryText: 'Try Again',
  onRefresh: () async {
    paginationManager.reset();
    await paginationManager.fetchNextPage();
  },
);

📖 API参考

PaginatedManagerList

属性 类型 描述
paginationManager PaginationManager 必填 - 分页逻辑管理器
itemBuilder Widget? Function(BuildContext, int, List<T>) 必填 - 列表项构建器
scrollThreshold double 触发分页的阈值(0.0到1.0)
showRefreshIndicator bool 启用/禁用下拉刷新
showRetryButton bool 显示/隐藏错误时的重试按钮
emptyItemsText String 空状态文本
retryText String 重试按钮文本
loadingPaginationWidget Widget? 自定义加载指示器
whenErrMessageFromPagination Function(String)? 分页错误处理器
fetchItemsFailureWidget Widget Function(String)? 自定义错误小部件构建器
errorTextStyle TextStyle? 错误消息样式
retryTextStyle TextStyle? 重试按钮文本样式
retryButtonStyle ButtonStyle? 重试按钮样式

PaginationManager

属性 类型 描述
repository PaginatedRepository 数据获取仓库
limitPerPage int 每页项目数量
items List<T> 当前项目列表
hasMore bool 是否还有更多项目
isLoading bool 加载状态

🤝 贡献

欢迎贡献!请随时提交Pull Request。

📄 许可证

本项目采用MIT许可证 - 详情见LICENSE文件。


示例代码

以下是pagination_manager插件的一个完整示例,展示如何在一个简单的应用中使用它。

// example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:pagination_manager/pagination_manager.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Pagination Manager Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const PostListScreen(),
    );
  }
}

// 示例数据模型
class Post {
  final int id;
  final String title;
  final String body;

  Post({
    required this.id,
    required this.title,
    required this.body,
  });

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }
}

// 示例仓库实现
class PostsRepository implements PaginatedRepository<Post> {
  @override
  Future<PaginationResult<Post>> fetchPaginatedItems(
      int page, int limitPerPage) async {
    try {
      // 模拟API延迟
      await Future.delayed(const Duration(seconds: 2));
      // 计算分页的起始和结束索引
      final startIndex = (page - 1) * limitPerPage;
      final endIndex = startIndex + limitPerPage;
      // 模拟API响应的虚拟数据
      final List<Post> posts = List.generate(
        100,
        (index) => Post(
          id: index + 1,
          title: 'Post ${index + 1}',
          body: 'This is the body of post ${index + 1}.',
        ),
      );

      // 模拟分页逻辑
      // 截取列表以获取分页项目
      final paginatedPosts = posts.sublist(
        startIndex,
        endIndex > posts.length ? posts.length : endIndex,
      );

      return PaginationResult.success(paginatedPosts);
    } catch (e) {
      //return PaginationResult.failure(e.toString());
      return const PaginationResult.failure('An error while fetching.');
    }
  }
}

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

  @override
  State<PostListScreen> createState() => _PostListScreenState();
}

class _PostListScreenState extends State<PostListScreen> {
  late final PaginationManager<Post> _paginationManager;

  @override
  void initState() {
    super.initState();
    _paginationManager = PaginationManager<Post>(
      repository: PostsRepository(),
      limitPerPage: 10,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Posts'),
      ),
      body: PaginatedManagerList<Post>(
        paginationManager: _paginationManager,
        itemBuilder: (context, index, items) {
          final post = items[index];
          return Card(
            margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: ListTile(
              title: Text(
                post.title,
                style: const TextStyle(fontWeight: FontWeight.bold),
              ),
              subtitle: Text(
                post.body,
                maxLines: 2,
                overflow: TextOverflow.ellipsis,
              ),
            ),
          );
        },
        // 自定义分页体验
        scrollThreshold: 0.8,
        showRefreshIndicator: true,
        emptyItemsText: 'No posts available',
        retryText: 'Try Again',
        // 处理分页错误
        whenErrMessageFromPagination: (message) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Error: $message')),
          );
        },
      ),
    );
  }
}

通过上述代码,您可以快速搭建一个具有分页功能的应用,并根据需要进行自定义和扩展。希望这对您有所帮助!


更多关于Flutter分页管理插件pagination_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter分页管理插件pagination_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用pagination_manager插件进行分页管理的代码案例。pagination_manager插件可以帮助你轻松实现分页加载数据的功能。

首先,你需要在pubspec.yaml文件中添加pagination_manager依赖:

dependencies:
  flutter:
    sdk: flutter
  pagination_manager: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来安装依赖。

接下来是一个简单的示例,展示如何使用pagination_manager进行分页加载:

import 'package:flutter/material.dart';
import 'package:pagination_manager/pagination_manager.dart';
import 'dart:async';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: PaginationScreen(),
    );
  }
}

class PaginationScreen extends StatefulWidget {
  @override
  _PaginationScreenState createState() => _PaginationScreenState();
}

class _PaginationScreenState extends State<PaginationScreen> with AutomaticKeepAliveClientMixin {
  final PaginationController<int> paginationController = PaginationController(pageLimit: 20);
  List<int> items = [];

  @override
  bool get wantKeepAlive => true;

  @override
  void initState() {
    super.initState();
    fetchData();
  }

  Future<void> fetchData() async {
    // 模拟网络请求延迟
    await Future.delayed(Duration(seconds: 1));

    // 获取当前页的数据
    List<int> pageData = List.generate(paginationController.pageLimit, (index) {
      return items.length + index + 1;
    });

    // 更新状态
    setState(() {
      items.addAll(pageData);
    });

    // 通知分页控制器数据已加载
    paginationController.notifyDataLoaded();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Pagination Manager Example'),
      ),
      body: PaginationView<int>(
        controller: paginationController,
        onPageRequested: (page) async {
          // 加载新页面的数据
          await fetchData();
        },
        itemBuilder: (context, item, index) {
          return ListTile(
            title: Text('Item ${item}'),
          );
        },
      ),
    );
  }
}

代码解释

  1. 依赖导入和安装

    • pubspec.yaml文件中添加pagination_manager依赖。
  2. 分页控制器

    • PaginationController<int>用于管理分页状态,这里我们设置每页加载20个数据项。
  3. 数据加载

    • fetchData方法模拟了一个网络请求,延迟1秒后生成当前页的数据并添加到items列表中。
    • 使用setState更新UI。
    • 调用paginationController.notifyDataLoaded()通知分页控制器数据已加载完成。
  4. 分页视图

    • PaginationView<int>用于显示分页数据。
    • onPageRequested回调在请求新页面时被调用,这里我们调用fetchData方法加载新页面的数据。
    • itemBuilder用于构建每个数据项的UI。

这个示例展示了如何使用pagination_manager插件进行基本的分页管理。你可以根据具体需求修改和扩展这个示例。

回到顶部