Flutter分页加载插件paging_view的使用

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

Flutter分页加载插件 paging_view 的使用

paging_view 是一个类似于 Android Jetpack Paging 库的插件,用于管理和显示分页列表。本文将详细介绍如何使用 paging_view 插件,并提供一个完整的示例代码。

Live Preview

您可以访问 Live Preview 查看 paging_view 的实际效果。

如何使用

1. 创建一个继承自 DataSource 的类

首先,您需要创建一个继承自 DataSource 的类,并实现 load 方法来获取数据。

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:paging_view/paging_view.dart';

class DataSourcePublicRepositories extends DataSource<int, Repository> {
  DataSourcePublicRepositories({
    required this.repository,
  });

  final GitHubRepository repository;

  [@override](/user/override)
  Future<LoadResult<int, Repository>> load(LoadAction<int> action) async =>
      switch (action) {
        Refresh() => await fetch(null),
        Prepend(key: final _) => const None(),
        Append(key: final key) => await fetch(key),
      };

  Future<LoadResult<int, Repository>> fetch(int? key) async {
    final PageData<int, Repository> data;
    if (key == null) {
      data = await repository.repositories();
    } else {
      data = await repository.repositories(since: key);
    }
    return Success(page: data);
  }
}

2. 在 Widget 中获取步骤 1 中创建的类实例

接下来,在您的 Widget 中获取该类的实例。

@riverpod
DataSourcePublicRepositories dataSourcePublicRepositories(
    DataSourcePublicRepositoriesRef ref) {
  final dataSource = DataSourcePublicRepositories(
    repository: ref.watch(gitHubRepositoryProvider),
  );

  ref.onDispose(() {
    dataSource.dispose();
  });

  return dataSource;
}

3. 将步骤 2 中获得的实例设置到 PagingListPagingGrid

最后,将数据源实例设置到 PagingListPagingGrid 组件中。

class HomePage extends ConsumerWidget {
  const HomePage({super.key});

  [@override](/user/override)
  Widget build(BuildContext context, WidgetRef ref) {
    final dataSource = ref.watch(dataSourcePublicRepositoriesProvider);

    final body = PagingList<int, Repository>(
      dataSource: dataSource,
      builder: (context, repository, index) => Card(
        child: ListTile(
          title: Text(repository.fullName),
          subtitle: Text(repository.description),
        ),
      ),
      errorBuilder: (context, e) => Center(
        child: Text('$e'),
      ),
      initialLoadingWidget: const Center(
        child: Padding(
          padding: EdgeInsets.all(16),
          child: CircularProgressIndicator.adaptive(),
        ),
      ),
      appendLoadingWidget: const Center(
        child: Padding(
          padding: EdgeInsets.all(16),
          child: CircularProgressIndicator.adaptive(),
        ),
      ),
      padding: const EdgeInsets.symmetric(horizontal: 16),
    );

    return Scaffold(
      appBar: AppBar(
        title: const Text('GitHub public repositories'),
      ),
      body: RefreshIndicator(
        onRefresh: () async => dataSource.refresh(),
        child: body,
      ),
    );
  }
}

完整示例 Demo

以下是一个完整的示例代码,展示了如何在应用中使用 paging_view 插件。

// main.dart
import 'package:example/app.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(
    const ProviderScope(
      child: App(),
    ),
  );
}

// app.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'home_page.dart';

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

// home_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'data_source_public_repositories.dart';

class HomePage extends ConsumerWidget {
  const HomePage({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context, WidgetRef ref) {
    final dataSource = ref.watch(dataSourcePublicRepositoriesProvider);

    final body = PagingList<int, Repository>(
      dataSource: dataSource,
      builder: (context, repository, index) => Card(
        child: ListTile(
          title: Text(repository.fullName),
          subtitle: Text(repository.description),
        ),
      ),
      errorBuilder: (context, e) => Center(
        child: Text('$e'),
      ),
      initialLoadingWidget: const Center(
        child: Padding(
          padding: EdgeInsets.all(16),
          child: CircularProgressIndicator.adaptive(),
        ),
      ),
      appendLoadingWidget: const Center(
        child: Padding(
          padding: EdgeInsets.all(16),
          child: CircularProgressIndicator.adaptive(),
        ),
      ),
      padding: const EdgeInsets.symmetric(horizontal: 16),
    );

    return Scaffold(
      appBar: AppBar(
        title: const Text('GitHub public repositories'),
      ),
      body: RefreshIndicator(
        onRefresh: () async => dataSource.refresh(),
        child: body,
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个关于如何在Flutter中使用paging_view插件来实现分页加载的简单示例代码。paging_view插件允许你创建分页加载列表,这对于需要分页从服务器获取数据的场景非常有用。

首先,确保你已经在pubspec.yaml文件中添加了paging_view依赖:

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

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

接下来是一个示例代码,展示了如何使用paging_view插件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Paging View Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final PagingController<int> _pagingController = PagingController(
    firstPageKey: 0,
    pageFuture: (pageKey) async {
      // 模拟从服务器获取数据
      await Future.delayed(Duration(seconds: 1)); // 模拟网络延迟
      final items = List.generate(
        20, // 每页20个项目
        (index) => pageKey * 20 + index + 1,
      );
      return PageData(
        items: items,
        nextPageKey: pageKey + 1,
      );
    },
    errorWidget: (context, error, stackTrace) {
      return Center(
        child: Text('加载失败: $error'),
      );
    },
    emptyWidget: (context) {
      return Center(
        child: Text('没有更多数据'),
      );
    },
  );

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Paging View Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: PagingView<int>(
          controller: _pagingController,
          builderDelegate: PagingViewBuilderDelegate<int>(
            itemBuilder: (context, item, index) {
              return ListTile(
                title: Text('Item $item'),
              );
            },
          ),
        ),
      ),
    );
  }
}

在这个示例中:

  1. PagingController:管理分页逻辑。firstPageKey是初始页面的键,pageFuture是一个异步函数,用于获取每页的数据。errorWidgetemptyWidget分别用于处理加载错误和没有更多数据的情况。

  2. PagingView:分页视图组件,接受PagingControllerbuilderDelegate作为参数。builderDelegate定义了如何构建每个项目。

  3. 模拟数据获取:在pageFuture函数中,我们使用Future.delayed模拟网络延迟,并生成每页的项目列表。

这个示例展示了基本的分页加载功能。在实际应用中,你可能需要根据具体的API接口和数据结构来调整pageFuture函数中的逻辑。

回到顶部