You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保存infinite_scroll_pagination中PagedListView的状态与已加载数据?

解决PagedListView在PageView切换时的状态与数据丢失问题

核心原因

PageView默认会销毁非当前显示的子页面,导致PagedListView内部的PagedViewController被回收,已加载的分页数据和状态随之丢失。PageStorage仅负责保存滚动位置,无法维护控制器的分页状态与数据,因此单独使用无效。

解决方案一:将PagedViewController提升至父组件

把PagedViewController的实例放在PageView所在的父组件中,让控制器生命周期与父组件绑定,避免子页面销毁时丢失数据。

// 父组件:持有PagedViewController并传递给子页面
class ParentPage extends StatefulWidget {
  @override
  _ParentPageState createState() => _ParentPageState();
}

class _ParentPageState extends State<ParentPage> {
  late final PagedViewController<int, Item> _pagedViewController;

  @override
  void initState() {
    super.initState();
    _pagedViewController = PagedViewController(
      firstPageKey: 0,
      pageRequest: (pageKey) async {
        // 替换为你的实际数据请求逻辑
        final items = await fetchItems(pageKey);
        return PagedResponse(
          data: items,
          nextPageKey: items.isNotEmpty ? pageKey + 1 : null,
        );
      },
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return PageView(
      children: [
        PagedListSubPage(controller: _pagedViewController),
        // 其他子页面
      ],
    );
  }
}

// 子页面:使用父组件传入的控制器
class PagedListSubPage extends StatelessWidget {
  final PagedViewController<int, Item> controller;

  const PagedListSubPage({super.key, required this.controller});

  @override
  Widget build(BuildContext context) {
    return PagedListView(
      pagedViewController: controller,
      builderDelegate: PagedChildBuilderDelegate<Item>(
        itemBuilder: (context, item, index) => ListTile(title: Text(item.name)),
      ),
    );
  }
}

解决方案二:使用AutomaticKeepAliveClientMixin保持子页面存活

通过该Mixin阻止PageView销毁非当前子页面,让页面的状态和控制器得以保留。

class PagedListSubPage extends StatefulWidget {
  @override
  _PagedListSubPageState createState() => _PagedListSubPageState();
}

class _PagedListSubPageState extends State<PagedListSubPage> with AutomaticKeepAliveClientMixin {
  late final PagedViewController<int, Item> _pagedViewController;

  @override
  void initState() {
    super.initState();
    _pagedViewController = PagedViewController(
      firstPageKey: 0,
      pageRequest: (pageKey) async {
        final items = await fetchItems(pageKey);
        return PagedResponse(
          data: items,
          nextPageKey: items.isNotEmpty ? pageKey + 1 : null,
        );
      },
    );
  }

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

  // 关键:返回true表示需要保持页面存活
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    // 必须调用super.build(context),否则Mixin不生效
    super.build(context);
    return PagedListView(
      pagedViewController: _pagedViewController,
      builderDelegate: PagedChildBuilderDelegate<Item>(
        itemBuilder: (context, item, index) => ListTile(title: Text(item.name)),
      ),
    );
  }
}

进阶优化

如果需要同时保留滚动位置,可以在PagedListView中添加pageStorageKey,结合上述方案使用:

PagedListView(
  pageStorageKey: const PageStorageKey('paged_list_key'),
  pagedViewController: controller,
  // ...其他配置
)

内容的提问来源于stack exchange,提问作者Kyrillus K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:31:04