2

我开始使用 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;
    }
  }
}

有人可以告诉我我在这里做错了什么吗?

4

2 回答 2

2

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

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);
      }
    });
于 2020-06-07T09:25:50.847 回答
1
//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 方法,它只运行一次(当它被插入到树中时)。之后,当 build 方法再次运行时,此代码将不会运行。

于 2020-06-07T16:35:10.710 回答