在 main.dart 和 PageView Controller 中结合 Provider (Pad) 和 ChangeNotifier (Provider) 报错多个滚动视图

Posted

技术标签:

【中文标题】在 main.dart 和 PageView Controller 中结合 Provider (Pad) 和 ChangeNotifier (Provider) 报错多个滚动视图【英文标题】:Combine Provider (Pad) and ChangeNotifier (Provider) in main.dart and PageView Controller error multiple scroll views 【发布时间】:2020-11-01 06:18:56 【问题描述】:

可能有人遇到过类似情况。

我正在使用 Bloc 模式提供程序(单例)以及 ChangeNotifierProvider。 当您从不同的子小部件实例化它们时,它们可以单独工作。 但我想从根 main.dart 实例化它们。

我正在尝试这个,它似乎进展顺利

//Provider Bloc Patern myapp1/blocs/provider_bloc.dart
//This Provider is used to manage other widgets
    import 'package:flutter/material.dart';
    import 'package:provider/single_child_widget.dart';
    
    class ProviderBloc extends InheritedWidget        
      //Singleton
      static ProviderBloc _instancia;
      factory ProviderBloc(Key key, SingleChildWidget child)
        if (_instancia==null)
          _instancia = new ProviderBloc._internal(key: key, child: child);
        
        return _instancia;
      
      ProviderBloc._internal( Key key, SingleChildWidget child)
        : super(key: key, child: child);
    
      @override
      bool updateShouldNotify(InheritedWidget oldWidget) => true;        
    

在我的主课中

import 'package:flutter/material.dart';
import 'package:myapp1/blocs/provider_bloc.dart';
import 'package:provider/provider.dart';
class MyApp extends StatelessWidget 
      @override
      Widget build(BuildContext context) 
        return ProviderBloc(
            child: ChangeNotifierProvider(
           create: (_) => new MainProvider(),
           child: MaterialApp(
           ...*rest of the code*

我的班级 MainProvider

//This Provider is used to mainly manage the PageController, and other widgets
    class MainProvider with ChangeNotifier
      int _currentPage = 1;
      PageController _pageController = new PageController();
      PageController get pageController => this._pageController;
    
      int get currentPage => this._currentPage;  
      set currentPage( int val ) 
        this._currentPage = val;
        _pageController.animateToPage(val, duration: Duration(milliseconds: 1), curve: Curves.easeOut );
        notifyListeners(); 
     

最后,问题出在我的 Home 小部件中,我的 PageView 由 MainProvider 类的 pageController 控制

class HomePage extends StatelessWidget 
    MainProvider mainProvider;
      @override
      Widget build(BuildContext context) 
        mainProvider = Provider.of<MainProvider>(context);
    
        return Scaffold(
                    resizeToAvoidBottomInset : true,        
                    resizeToAvoidBottomPadding: false,
                    body: PageView(
                      controller: mainProvider.pageController,      
                      children: <Widget>[
                        Container(),
                        Container(),
                        Container(),
    
                      ],
                    ),
                    floatingActionButton: FloatingActionButton(
                        child: Icon(
                            Icons.search,
                          ),
                          onPressed: ()
                                    mainProvider.currentPage = 0;
                          
                      ),
           ...*rest of the code*

当我按下 FloatingActionButton 来改变 PageView 的 currentPage 时,它​​会抛出错误

════════ Exception caught by gesture ═══════════════════════════════════════════
The following assertion was thrown while handling a gesture:
ScrollController attached to multiple scroll views.
'package:flutter/src/widgets/scroll_controller.dart':
Failed assertion: line 111 pos 12: '_positions.length == 1'

我不明白为什么,如果我没有在任何其他小部件中使用该 pageController

【问题讨论】:

为什么在另一个ChangeNotifier 中有一个scrollController?我看不出有什么好的理由这样做。这只是糟糕的架构。你检查flutter_bloc了吗? 基本上我这样做是为了从其他儿童小部件中更改页面,我在一些示例中看到了它。或者会有其他更好的方法来做到这一点,以便它可以与我的 Provider Bloc 一起工作? 【参考方案1】:

PageController 已经是一个 ChangeNotifier,不需要将它包装在其他 ChangeNotifier 类中,何不尝试创建它并将其传递给 ChangeNotifierProvider.value?

  class MyApp extends StatelessWidget 
  PageController _pageController = PageController();

  @override
  Widget build(BuildContext context) 
    return ProviderBloc(
        child: ChangeNotifierProvider.value(
       value: _pageController,
       child: MaterialApp(
       ...*rest of the code*

在首页

class HomePage extends StatelessWidget 
PageController pageController;
  @override
  Widget build(BuildContext context) 
    pageController = Provider.of<PageController>(context, listen: false);

    return Scaffold(
                resizeToAvoidBottomInset : true,        
                resizeToAvoidBottomPadding: false,
                body: PageView(
                  controller: pageController,      
                  children: <Widget>[
                    Container(),
                    Container(),
                    Container(),

                  ],
                ),
                floatingActionButton: FloatingActionButton(
                    child: Icon(
                        Icons.search,
                      ),
                      onPressed: ()
                                pageController.animateToPage(0, duration: Duration(milliseconds: 1), curve: Curves.easeOut );
    
                      
                  ),
       ...*rest of the code*

【讨论】:

你好 EdwynZN 这个想法似乎不错.. 我会试试的。但是,我想知道如何对 MainProvider 中的其他对象执行此操作,以便其他子小部件可以使用它们。我有处理 MainProvider 中的 pageController 和其他对象的想法,因为其他孩子将对 pageController 进行更改 对象是否依赖于页面控制器的值?您可以创建一个 ChangeNotifierProxyProvider 以便在页面控制器更改时更新 它们不依赖于 pageController,但我已经使用 notifyListener 获取和设置 -- bool _editPage = false; bool get editPage => this._editPage;设置 editPage (bool val) this._editPage = val;通知监听器(); 在这种情况下,MultiProvider 中只有 2 个 ChangeNotifierProvider

以上是关于在 main.dart 和 PageView Controller 中结合 Provider (Pad) 和 ChangeNotifier (Provider) 报错多个滚动视图的主要内容,如果未能解决你的问题,请参考以下文章

编辑器在保存时打开 main.dart

如何从除 main.dart 之外的其他文件中获取参考

出现“找不到目标文件”lib\main.dart“之类的错误。”在颤振中构建 APK

练习main.dart1

Flutter:是不是可以在 main.dart 中实现一次快餐栏,例如,当连接状态发生变化时,用于所有屏幕

在调试模式下在 Windows 上启动 lib/main.dart... 无法构建:找不到 vcvars64.bat