从非小部件类访问 Flutter Bloc

Posted

技术标签:

【中文标题】从非小部件类访问 Flutter Bloc【英文标题】:Flutter Bloc access from NOT a widget class 【发布时间】:2020-09-26 11:16:22 【问题描述】:

一个设计模式类型的问题。我正在使用 Flutter 的 TextToSpeech 包。

用户按下播放 (UI) 这会将播放事件传递给 Bloc,该 bloc 创建一个 TTSPlayer 对象并将字符串列表 (TTSScript) 传递给它。 TTS 通过迭代读出列表中的每个字符串。

问题: 我希望每次 TTSPlayer 移动到列表中的下一个字符串时,该集团都调度一个事件,以便我可以在屏幕上显示当前字符串。

但是: 如何将 'currentTextUpdatedEvent' 从 TTSPlayer 传递到 bloc,然后我可以将其传递回 UI。

我试过了: 我希望我能做这样的事情:

BlocProvider.of<TTSPlayerBloc>(context).add(updateCurrentTtsString(currentTtsString));

来自 TTSPlayer 类...当然,这个类不是一个没有上下文的小部件。我应该使用回调吗?什么在这里工作......?我应该将 TTSPlayer 移出该区域并移入屏幕吗?

  Stream<TTSPlayerState> mapEventToState(TTSPlayerEvent event) async* 
    TTSPlayer lessonPlayer = new TTSPlayer();
  
    if (event is TTSPlayerScreenLoadedEvent) 
      //get the script
      TTSScript myScript = await scriptRepository.fetchScript(event.script);
      // play it
      lessonPlayer.play(myLessonScript);
      //// How can the lessonplayer inform this Stream every time it's current string has changed? 
      yield TTSPlayingState();
    

    /// something like this??? But how to send this event from TTSPlayer class... 
    if (event is updateCurrentTtsString)
    yield NewStringState(newstring)
    

更新 所以,我在 TTSPlayer 中添加了一个回调。所以这个集团现在看起来像这样:

      Stream<TTSPlayerState> mapEventToState(TTSPlayerEvent event) async* 
        TTSPlayer lessonPlayer = new TTSPlayer();
   ///
    final newStringCallback = () 
      this.add(updateCurrentTtsString(lessonPlayer.currentTtsString));
    ;
   ///
        if (event is TTSPlayerScreenLoadedEvent) 
          //get the script
          TTSScript myScript = await scriptRepository.fetchScript(event.script);
          // play it
          lessonPlayer.play(myLessonScript, newStringCallback););
          yield TTSPlayingState();
        


    if (event is updateCurrentTtsString) 
      print('New String');
      yield TTSPlayingState(event.currentString);
    

如果删除 yield 语句,每次 IF 都会触发 updateCurrentStringEvent...当我包含 yield 语句时,它会阻止 TTSPlayer 继续。我不明白为什么玩家会停下来,但确实如此。

【问题讨论】:

【参考方案1】:

解决方案:

好的,经过一番折腾,我在集团内部设置了一个新流,如下所示:

  final currentStringStreamController = StreamController<String>();
  StreamSink<String> get currentStringSink => currentStringStreamController.sink;
  Stream<String> get currentStringStream => currentStringStreamController.stream;

然后,在我在原始帖子中设置的回调中,我更改了:

 this.add(updateCurrentTtsString(lessonPlayer.currentTtsString));

到:

  currentStringSink.add(string);

然后使用 async 包中的 darts streambuilder 构建一个文本框小部件。

希望它可以帮助某人。

【讨论】:

以上是关于从非小部件类访问 Flutter Bloc的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中使用 BLoC - 在有状态小部件与无状态小部件中的使用

Flutter BLoC 库:将 TextEditingController 对象保存在哪里:在 State、BLoC / Cubit 类中还是在小部件中?

Flutter BLoC - 状态不会触发小部件重建

Flutter Bloc 不断重建小部件而不改变状态

Flutter - 关闭小部件时 BLoC 流实例会导致内存泄漏吗?

Flutter Bloc 状态管理