从非小部件类访问 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 类中还是在小部件中?