上一篇最後講到...
「另外啟動一條執行序,然後不停檢查這個『synthesis.speaking』吧!」
什麼叫執行緒?這裡講的是讓外行人理解「技術領域有這個議題與技巧」與「這個議題與技巧為何被討論」而已,但實際上怎麼做、或有什麼魔鬼藏在裡頭....讓AI來幫忙煩惱吧!
執行緒的英文稱為「Thread」,中文可以寫執行緒、執行序、線程,都是指這件事。
它的功能在於:「多核心電腦」一次可以執行很多軟體、一個軟體可以執行很多功能....但是可以在「多核心電腦」上執行的軟體要如何在「單核心電腦」上正常運作呢?(記得有個東西叫Java嗎?)這就是執行序!從軟體層面去模擬多個核心、將「事情」做排程後排隊依序執行。
講白話一點,「把這件事情丟到背景去執行」這樣的事情就是靠「執行序」做出來的。
不同程式語言設計執行序的方式都不太一樣,甚至還有多種設計執行序的方法。
在Flutter上,剛好就是這種情況。(唉...我想念Java。)
好!問問AI!(這次做的功能有點心血來潮、改動幅度有點大!準備好了!)
「請依序以_listData中的InputData爲資料執行_speak功能,另外開啟執行序,會檢查_listData是否還有資料等著被執行,和_speak是否仍在播放語音,當兩項都為否,則關閉錄音。」
結果...(一次就完成,而且可以無閃退的執行,雖然功能尚未完成。)
final WebRecorder _recorder = WebRecorder();
html.SpeechSynthesis? _synthesis;
html.SpeechSynthesisUtterance? _utterance;
Queue<InputData> _queue = Queue<InputData>();
TtsRecorder() {
_synthesis = html.window.speechSynthesis;
_utterance = html.SpeechSynthesisUtterance();
}
Future<void> speakAndRecord(List<InputData> inputDataList) async {
if (inputDataList.isEmpty) {
return;
}
// Add all InputData objects to the queue
_queue.addAll(inputDataList);
// Start recording
await _recorder.startRecording();
// Process the queue
processQueue();
}
void processQueue() {
if (_queue.isNotEmpty) {
var inputData = _queue.removeFirst();
if (inputData.value is String) {
// Speak the text
_utterance!.text = inputData.value;
_synthesis!.speak(_utterance!);
checkSpeaking();
}
}
}
Future<void> checkSpeaking() async {
await Future.delayed(Duration(milliseconds: 1000));
if (_synthesis?.speaking??false) {
// If _synthesis is still speaking, wait for a short delay and then check again
checkSpeaking();
} else if (_queue.isNotEmpty) {
// If _synthesis is not speaking but there are still InputData objects in the queue, process the queue
processQueue();
} else {
// If _synthesis is not speaking and the queue is empty, stop recording
_recorder.stopRecording();
}
}
(為什麼未完成?下一篇解釋啦!)