PageController 未在 Flutter 的 PageView 模块中正确设置。位置不为空错误弹出

PageController not set properly within the PageView module in Flutter. Positions not empty error popping up

我开始使用 Flutter 框架进行编程,并立即注意到出现了一个奇怪的问题(有关详细信息,请参见下文)。

问题发生在: 返回 MainScreen 并尝试通过按下按钮从 PageView 中的屏幕切换来更改 PageView 索引后,我收到此错误:

[ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: 'package:flutter/src/widgets/scroll_controller.dart': Failed assertion: line 110 pos 12: '_positions.isNotEmpty': ScrollController not attached to any scroll views.

这是我的主屏幕:

class MainScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MainScreenState();
}

class MainScreenState extends State<MainScreen> {
  PageController _controller;

  void _onLoad() {
    _controller = PageController();
    ShareBloc.getInstance().pageViewIndexStream.listen((index) {
      _controller.animateToPage(index,
          duration: Duration(milliseconds: 200), curve: Curves.easeInOut);
    });
  }

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

  @override
  Widget build(BuildContext context) {
    _onLoad();

    return PageView(
      controller: _controller,
      physics: NeverScrollableScrollPhysics(),
      children: [
        FirstScreen(),
        SecondScreen(),
      ],
    );
  }
}

这是我的 RxDart Sharable 文件:

import 'package:rxdart/rxdart.dart';

class ShareBloc {
  static ShareBloc _instance;
  BehaviorSubject<dynamic> _subjectCounter;

  static ShareBloc getInstance() {
    if (_instance == null) _instance = ShareBloc();
    return _instance;
  }

  ShareBloc() {
    _subjectCounter = new BehaviorSubject<dynamic>();
  }

  Stream<dynamic> get getStream => pageViewIndexStream.stream;

  void onShare(dynamic data) {
    _subjectCounter.sink.add(data);
  }

  void dispose() {
    if (_subjectCounter != null) {
      _subjectCounter.close();
      _instance = null;
    }
  }
}

谁能告诉我我做错了什么?

为我解决这个问题的正确方法是包装这部分:

ShareBloc.getInstance().pageViewIndexStream.listen((index) {
      _controller.animateToPage(index,
          duration: Duration(milliseconds: 200), curve: Curves.easeInOut);
    });

与:

ShareBloc.getInstance().pageViewIndexStream.listen((index) {
      if (_controller.hasClients) { // <-- this is the fix!
        _controller.animateToPage(index,
            duration: Duration(milliseconds: 200), curve: Curves.easeInOut);
      }
    });
//This will run just once
@override
void initState() {
    super.initState();
    //This code is the same as your _onLoad method, you don't neet to run it on the build method anymore
    _controller = PageController();
    ShareBloc.getInstance().pageViewIndexStream.listen((index) {
      _controller.animateToPage(index,
          duration: Duration(milliseconds: 200), curve: Curves.easeInOut);
    });
}

就像 dispose 方法一样,StatefulWidget 有一个 initState 方法,它 运行 只执行一次(当它被插入到树中时)。之后,当构建方法再次 运行s 时,此代码将不会 运行.