如何在 initState 方法中访问颤振块?

Posted

技术标签:

【中文标题】如何在 initState 方法中访问颤振块?【英文标题】:how to access flutter bloc in the initState method? 【发布时间】:2020-01-10 02:13:18 【问题描述】:

在下面显示的代码中,在获取 BuildContext 对象后,从 build 方法中调用了 dispatch 事件。如果我想做的是在 initState 方法本身的页面开始处处理期间调度事件怎么办?

如果我使用 didChangeDependencies 方法,则会收到此错误: BlocProvider.of() called with a context that does not contain a Bloc of type FileManagerBloc. 如何解决这个问题?

  @override
  Widget build(BuildContext context) 
    return Scaffold(
        body: BlocProvider<FileManagerBloc>(
          builder: (context)=>FileManagerBloc(),
          child: SafeArea(
      child: Container(
          child: Column(
            children: <Widget>[
              Container(color: Colors.blueGrey, child: TopMenuBar()),
              Expanded(
                child: BlocBuilder<FileManagerBloc,FileManagerState>(
                  builder: (context , state)
                    return GridView.count(
                      scrollDirection: Axis.vertical,
                      physics: ScrollPhysics(),
                      crossAxisCount: 3,
                      crossAxisSpacing: 10,
                      children: getFilesListWidget(context , state),
                    );
                  ,
                ),
              )
            ],
          ),
      ),
    ),
        ));
  

  @override
  void dispose() 
    super.dispose();
  

  @override
  void didChangeDependencies() 
    logger.i('Did change dependency Called');
    final FileManagerBloc bloc = BlocProvider.of<FileManagerBloc>(context) ;
    Messenger.sendGetHomeDir()
        .then((path) async 
      final files = await Messenger.sendListDir(path);
        bloc.dispatch(SetCurrentWorkingDir(path)) ;
        bloc.dispatch(UpdateFileSystemCacheMapping(path , files)) ;
    );
  

【问题讨论】:

【参考方案1】:

您可以在didChangeDependencies 方法而不是initState 中使用它。

示例

 @override
  void didChangeDependencies() 
    final CounterBloc counterBloc = BlocProvider.of<CounterBloc>(context);
    //do whatever you want with the bloc here.
    super.didChangeDependencies();
  

【讨论】:

BlocProvider.of(上下文出现错误,我已经更新了我的问题,请提出修复建议 不知道为什么这被否决了。这是访问集团的合法方式。我在didChangeDependencies 中使用它。在父小部件中我有 BlocProvider 所以我可以访问子小部件中的块。每次我导航到特定视图时,我都会使用它来使用 counterBloc.add(...) 触发事件。 在 didChangeDependencies 中触发 bloc 事件是非常糟糕的做法 - 特别是检查在复杂的小部件中可以触发多少次。在这里使用上下文是安全的,但不一致。【参考方案2】:

问题是您正在 BlocProvider 内初始化 FileManagerBloc 的实例,这当然是父小部件无法访问的。我知道这有助于自动清理Bloc,但如果你想在initStatedidChangeDependencies 中访问它,那么你必须像这样在父级初始化它,

FileManagerBloc _fileManagerBloc;

@override
void initState() 
  super.initState();
  _fileManagerBloc= FileManagerBloc();
  _fileManagerBloc.dispatch(LoadEducation());


@override
  Widget build(BuildContext context) 
    return Scaffold(
        body: BlocProvider<FileManagerBloc>(
          builder: (context)=> _fileManagerBloc,
          child: SafeArea(
      child: Container(
          child: Column(
            children: <Widget>[
              Container(color: Colors.blueGrey, child: TopMenuBar()),
              Expanded(
                child: BlocBuilder<FileManagerBloc,FileManagerState>(
                  builder: (context , state)
                    return GridView.count(
                      scrollDirection: Axis.vertical,
                      physics: ScrollPhysics(),
                      crossAxisCount: 3,
                      crossAxisSpacing: 10,
                      children: getFilesListWidget(context , state),
                    );
                  ,
                ),
              )
            ],
          ),
      ),
    ),
        ));
  

  @override
  void dispose() 
    _fileManagerBloc.dispose();
    super.dispose();
  

  @override
  void didChangeDependencies() 
    logger.i('Did change dependency Called');
    Messenger.sendGetHomeDir()
        .then((path) async 
      final files = await Messenger.sendListDir(path);
        _fileManagerBloc.dispatch(SetCurrentWorkingDir(path)) ;
        _fileManagerBloc.dispatch(UpdateFileSystemCacheMapping(path , files)) ;
    );
  

或者,如果FileManagerBloc 在祖父母Widget 上提供/初始化,那么它可以通过BlocProvider.of&lt;CounterBloc&gt;(context);this 级别轻松访问

【讨论】:

以上是关于如何在 initState 方法中访问颤振块?的主要内容,如果未能解决你的问题,请参考以下文章

颤振异步调用不会在 initState() 中异步运行

在颤振中在 initstate() 之前调用了dependOnInheritedElement()

无法在颤振中访问 Firestore 本地仿真器套件

Flutter应用打开时如何从sqlite数据库加载初始状态数据

如何在flutter中调用initState中的异步方法

如何在颤动中从父小部件调用子小部件的initState()方法