Flutter异步发送MIDI SysEx消息时UI冻结、进度条不显示如何解决
问题原因
1. 同步阻塞导致UI无法刷新
你调用了dart:io库的sleep()方法,这是同步阻塞函数,会直接卡住Flutter主UI线程的事件循环。即便send方法声明为异步,sleep本身不会让出执行权,你调用setState后UI要等所有sleep执行完毕才会批量渲染,自然看不到进度更新。
2. 进度值范围不匹配
LinearProgressIndicator的value属性要求传入0~1区间的浮点数,你当前计算逻辑_progress = 100/chunks*chunkCount得到的是0~100的数值,超过1之后进度条会一直显示满格状态,看不到变化。
修复方案
- 把同步的
sleep替换为异步等待Future.delayed,不会阻塞UI线程,同时给Flutter留出渲染UI的时间 - 调整进度计算逻辑,将值缩放到0~1区间
- 可选优化:如果
sendData方法是异步的,建议增加await调用,确保上一块数据发送完成再处理下一块,避免MIDI消息丢包
修复后的send方法代码:
Future<void> send(Uint8List _syxData) async { _midiCommand.connectToDevice(oxiOne.OxiOne().device); int chunkSize = _syxData.indexWhere((element) => element == 0xf7) + 1; int chunks = (_syxData.lengthInBytes % chunkSize == 0) ? _syxData.lengthInBytes ~/ chunkSize : _syxData.lengthInBytes ~/ chunkSize + 1; for (int chunkCount = 1, start = 0, end = chunkSize; chunkCount <= chunks; chunkCount++ ){ if (chunkCount == chunks){ dev.log("sending last chunk: "); // 如果sendData是异步方法,建议加await await _midiCommand.sendData(_syxData.sublist(start)); } else { dev.log("last byte of this chunk $chunkCount is ${_syxData[end-1]}"); await _midiCommand.sendData(_syxData.sublist(start, end)); } start = chunkCount*chunkSize; end = start+chunkSize; // 替换同步sleep为异步等待 await Future.delayed(const Duration(milliseconds: 190)); if (chunkCount == chunks) { return; } else { setState(() { // 调整进度值到0~1区间 _progress = chunkCount / chunks; }); } } }
内容的提问来源于stack exchange,提问作者Noir
相关产品推荐
相关产品推荐

