【问题标题】:How to synchronize a call from the asynchronous function in dart如何同步dart中异步函数的调用
【发布时间】:2020-04-12 13:36:50
【问题描述】:

我正在开发我在 Flutter 中的第一个应用程序,我对 Java 和 js 有一些经验,但我之前从未使用过 Flutter,如果我的问题对您来说很荒谬,非常抱歉。

该应用程序是语音助手聊天机器人,它应该对客户收到的每条新消息执行文本转语音,我的问题是,由于我使用的是 firebase 消息传递,因此我收到的所有请求都在异步调用中,但我需要同步对文本到语音服务的访问,否则我会遇到一个文本中断另一个文本的问题。

这是我的代码目前的样子: Firebase 消息传递:

onMessage: (Map<String, dynamic> message) {
        return this.handleBotMessage(appState, message);
},

决定如何处理每条特定消息的方法:

Future handleBotMessage(
    Store<AppState> store,
    Map<String, dynamic> dataJson,
  ) {
      #logic that convert the message into json and extracts the message type

      if (type == MessageType.CHAT_MESSAGE) {
        return handleChatMessage(store, subtype, messageMap);
      }
  }

处理短信的方法:

Future<dynamic> handleChatMessage(
    Store<AppState> store,
    MessageSubtype subtype,
    Map<String, dynamic> message,
  ) {
    #Text to speach is build as a singleton and this always returns the same instance
    TextToSpeech tts = TextToSpeech();
    if (subtype == MessageSubtype.TEXT) {
      TextMessage textMessage = TextMessage.fromJson(message);
      return tts
          .speak(textMessage.text)
          .then((result) => store.dispatch(NewBotMessageAction(textMessage)));
    } else if (subtype == MessageSubtype.QUICK_REPLY) {
      QuickReplyMessage qrMessage = QuickReplyMessage.fromJson(message);
      return tts
          .speak(qrMessage.text)
          .then((result) => store.dispatch(NewQrOptionsAction(qrMessage)));
    } else {
      throw new Exception('Unexpected message subtype!');
    }
  }

实际执行文本到语音的方法

Future<dynamic> speak(String text) async {
    return flutterTts.speak(text).then((resp) {
      ttsRunning = false;
      print(resp);
      return resp;
    }, onError: (obj, st) {
      ttsRunning = false;
      print(obj);
      print(st.toString());
    });
  }

文字转语音初始化

Future init() async {
    await flutterTts.setLanguage("en-US");
    var res = await flutterTts.isLanguageAvailable("en-US");
    print(res);
    return res;
  }

https://pub.dev/packages/flutter_tts

【问题讨论】:

  • 我认为等待speak方法是不够的,你需要检查flutterTts.setCompletionHandler回调,如果消息到达太快并且相互中断,可能结合队列?

标签: flutter dart firebase-cloud-messaging text-to-speech


【解决方案1】:

好的,我找到了解决方案,问题正如 frank06 所指出的那样,flutter tts 立即完成未来,而不是在说出整个短语之后。
所以这是我的解决方案,它并不完美,但它有效:

Completer completer;
Future<dynamic> speak(String text) {
    print('Started speeking');
    print(new DateTime.now().toIso8601String());
    if (TextToSpeech.lastRequest == null) {
      lastRequest = _executeSpeech(text);
    } else {
      lastRequest = lastRequest.then((resp) {
        return _executeSpeech(text);
      });
    }
    return lastRequest;
  }

  Future<dynamic> _executeSpeech(String text) {
    completer = Completer();
    flutterTts.speak(text).then((resp) {
      ttsRunning = false;
      print(resp);
      return resp;
    }, onError: (obj, st) {
      ttsRunning = false;
      print(obj);
      print(st.toString());
    });
    return completer.future;
  }


flutterTts.setCompletionHandler(() {
  print('Finished speeking');
  print(new DateTime.now().toIso8601String());
  ttsState = TtsState.stopped;
  completer.complete(ttsState);
});

flutterTts.setErrorHandler((msg) {
  ttsState = TtsState.stopped;
  completer.complete(ttsState);
});

【讨论】:

    【解决方案2】:

    如果您不希望新消息打断正在说话的内容,您可以将它们排队。这样,新消息将等待当前消息完成。看看这个方法:

    Queue of Future in dart

    【讨论】:

      猜你喜欢
      • 2012-07-25
      • 2020-12-20
      • 2015-03-19
      • 2013-07-12
      • 2014-06-14
      • 1970-01-01
      • 2020-10-13
      • 2012-02-25
      • 2020-04-20
      相关资源
      最近更新 更多