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

使用PageView与Provider时触发PageController.page访问错误,求解决方案

解决PageView与Provider结合时的PageController.page访问错误

问题场景

在使用PageView组件和Provider状态管理实现分步注册页面时,触发以下断言错误:

Error: "PageController.page cannot be accessed before a PageView is built with it.
'package: flutter/src/widgets/page_view.dart':
Failed assertion: line 173 pos 7: 'positions.isNotEmpty'"

相关代码

RegistrationModel 状态模型

class RegistrationModel with ChangeNotifier {
  int _pageIndex;
  int _currentPage = 0;

  setCurrentPage(int value) {
    _currentPage = value;
    notifyListeners();
  }
}

注册页面组件

class RegistrationPagesView extends StatelessWidget {
  PageController pageController;

  RegistrationPagesView({this.pageController});

  @override
  Widget build(BuildContext context) {
    return Consumer<RegistrationModel>(
        builder: (ctx, registrationModel, widget) {
          final pageView = PageView(
          onPageChanged: (value) {
            ctx.read<RegistrationModel>().setCurrentPage(value);
          },
        controller: pageController,
        scrollDirection: Axis.horizontal,
        pageSnapping: true,
        physics: const NeverScrollableScrollPhysics(),
        children: [
          FirstStepRegisterPage(),
          NewsPageRegistr(),
          MagazinePageRegistr(),
          RightPageRegistr(),
        ],
      );
      if(registrationModel.currentPage != pageController.page.floor()) {
        pageController.jumpToPage(registrationModel.currentPage);
      }
        return pageView;
    });
  }
}

问题原因与修复方案

核心原因

错误源于PageView未完成构建、未与PageController绑定前,直接访问了pageController.page属性——此时PageController的positions列表为空,触发了Flutter内部的断言检查。

修复步骤

  1. 延迟页面跳转逻辑至Widget构建完成后
    使用addPostFrameCallback确保在Widget树渲染完成后再执行页面跳转判断,避免提前访问未初始化的pageController.page:
class RegistrationPagesView extends StatelessWidget {
  final PageController pageController;

  RegistrationPagesView({required this.pageController});

  @override
  Widget build(BuildContext context) {
    return Consumer<RegistrationModel>(
      builder: (ctx, registrationModel, widget) {
        // 帧后回调:确保PageView已绑定PageController
        WidgetsBinding.instance.addPostFrameCallback((_) {
          // 增加空安全判断,避免page为null时出错
          if (registrationModel.currentPage != pageController.page?.floor()) {
            pageController.jumpToPage(registrationModel.currentPage);
          }
        });

        return PageView(
          onPageChanged: (value) {
            ctx.read<RegistrationModel>().setCurrentPage(value);
          },
          controller: pageController,
          scrollDirection: Axis.horizontal,
          pageSnapping: true,
          physics: const NeverScrollableScrollPhysics(),
          children: const [
            FirstStepRegisterPage(),
            NewsPageRegistr(),
            MagazinePageRegistr(),
            RightPageRegistr(),
          ],
        );
      },
    );
  }
}
  1. 补充状态模型的getter方法
    原模型缺少currentPage的读取方法,导致无法正确获取状态值,需补充:
class RegistrationModel with ChangeNotifier {
  int _currentPage = 0;

  // 补充currentPage的getter
  int get currentPage => _currentPage;

  setCurrentPage(int value) {
    // 避免重复触发通知优化性能
    if (_currentPage != value) {
      _currentPage = value;
      notifyListeners();
    }
  }
}
  1. 初始化时同步PageController与状态模型
    在父组件创建PageController时,直接同步状态模型的初始页面,减少首次渲染的跳转操作:
// 父组件中初始化PageController
final registrationModel = Provider.of<RegistrationModel>(context, listen: false);
final pageController = PageController(initialPage: registrationModel.currentPage);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 07:00:57