颤振和块异步产量

Posted

技术标签:

【中文标题】颤振和块异步产量【英文标题】:flutter and bloc asynchronous yield 【发布时间】:2020-06-18 19:45:14 【问题描述】:

我正在使用带有 BLoC 模式的颤振(使用 flutter_bloc 库)并且我有这些事件:

PersonalFileAddedEvent(File file), PersonalFileUploadEvent(PersonalFile file)(都从PersonalFileEvent扩展而来)

File 是来自文件选择器的文件,PersonalFile 是具有以下枚举状态的类:READY_TO_UPLOAD, UPLOADING, UPLOAD_FINISHED

以及来自 BLoC 的这个状态:

PersonalFileListLoadedState(List<PersonalFile> files)(从PersonalFileListState扩展)

当用户选择一个文件时,UI 调用事件 PersonalFileAddedEvent 并将其传递给 BLoC,该 BLoC 创建一个 PersonalFile 对象并将其状态设置为 READY_TO_UPLOAD。这个PersonalFile 对象得到 添加到包含用户正在添加(和上传)的所有 PersonalFile 的列表中。然后 BLoC 使用 PersonalFileListLoadedState(blocPersonalFileList) 向 UI 响应 (yield) 以呈现信息。

添加后,会在 UI 中为 PersonalFile 呈现一个“立即上传”按钮。按下时,它会调用PersonalFileUploadEvent 事件并将PersonalFile 发送到 BLoC 以启动上传过程(分段上传)。 收到事件后,BLoC 立即将此 PersonalFile 的状态更新为 UPLOADINGyield PersonalFileListLoadedState 状态,同时更新 PersonalFile 的状态以供 UI 显示它正在上传。

上传multipart文件的方法是async:

Future<PersonalFile> upload(PersonalFile file) async  //upload code 

这是来自 flutter_bloc 的 mapEventToState:

Stream<PersonalFileListState> mapEventToState(PersonalFileEvent event) async* 

在这个 mapEventToState 方法中,我正在等待上传方法将 PersonalFile 的状态更新为 UPLOAD_FINISHED

问题从现在开始,因为用户从文件选择器中添加了几个文件,并按下了所有“上传”按钮。 BLoC 在接收到第一个事件后被阻塞并处理“类似同步”的事件和 UI 就好像在第一个完成(然后是下一个,依此类推)之前没有按下另一个 PersonalFile 的“上传”按钮。

在一个事件被完全处理(上传完成)后,下一个事件被处理,这是有道理的,因为我正在等待上传方法完成。

如何编写此代码,以便如果用户在 UI 中按下多个“上传”按钮,BLoC 不会被阻止(因此 UI 因为 BLoC 无法yield 新状态)和所有文件被上传 并行,但仅在每个人完成之前,BLoC 发送 PersonalFile 的新 List 并将其状态更改为 UPLOAD_FINISHED

我已尝试将上传方法的签名更改为:

Stream<PersonalFile> upload(PersonalFile file) async*  //upload code 

并使用:

.then((file)  yield PersonalFileListLoadedState(listWithUpdatedPersonalFileStatus) )

但是里面的代码永远不会被执行。我尝试调试,但无法到达断点。

【问题讨论】:

【参考方案1】:

不确定您是如何调用 bloc 来启动进程上传的。 但是,如果您在按下按钮时使用bloc.add(event),则应该以异步方式对其进行处理,并根据需要产生新的状态。

另外请注意,当您处理状态更改时,如果多次产生相同的状态,侦听器只会侦听一次,因此您不会在 UI 中看到多个更新。

希望这会有所帮助。

【讨论】:

没错,在集团内部添加新事件非常有用。非常感谢! @HollandSalazar 你是如何在 bloc 中添加事件的?你能帮我写一些代码吗? 例如,当您按下按钮时,您将该事件添加为bloc.add(my_event),因此在您的块中,在处理事件的方法中您可以执行以下操作:Stream&lt;PrintJobsState&gt; _addPrintJob(PrintJob job, StorageProvider provider, StorageFile file) async* /// process your event. add(new_event); /// Continue processing your event

以上是关于颤振和块异步产量的主要内容,如果未能解决你的问题,请参考以下文章

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

颤振/飞镖异步不等待

异步功能完成后颤振 setState()

颤振异步等待未按预期工作

颤振/飞镖:如何在飞镖 FFI 中使用异步回调?

颤振错误:<异步挂起>