【问题标题】:Dart: cancelable post delay / futureDart:可取消的后期延迟/未来
【发布时间】:2019-05-29 04:42:39
【问题描述】:

我是 Flutter 的新手,我想通过调用 API 从 InputField 翻译一些文本。但是我不想在每次击键时都调用它,而是只在用户暂停输入时调用它。

在 Android 上,我只会使用 Handler 类和 postDelay() 并事先调用 removeAllCallbacksAndMessages(null)。有没有办法在 Dart 上做类似的事情?

这是我当前的代码:

Future<String> getTranslation(String query, Language from, Language to) async {
    // cancel here if a call to this function was less than 500 millis ago.
    return Future.delayed(const Duration(milliseconds: 500), () {
      return _translator.translate(query, from: from.code, to: to.code)
    });
  }

编辑 1

我正在从我的 Bloc 中调用代码,如下所示:

@override
  Stream<State> mapEventToState(Event event) async* {
    if (event is QueryChangeEvent) {
      yield TextTranslationChangeState(
          query: event.query ?? "",
          translation: await _repo.getTranslation(event.query, currentState.fromLang, currentState.toLang));
  }

这就是为什么我不能在未来调用.then(),因为我无法从嵌套函数的块中产生新状态。

感谢任何帮助!

【问题讨论】:

标签: flutter dart dart-async


【解决方案1】:

可以通过CancelableOperation实现取消Future异步操作。

这是一个示例(p.s 我简化了您的方法签名以便我轻松测试它)

  CancelableOperation cancellableOperation;

  Future<dynamic> fromCancelable(Future<dynamic> future) async {
    cancellableOperation?.cancel();
    cancellableOperation = CancelableOperation.fromFuture(future, onCancel: () {
      print('Operation Cancelled');
    });
    return cancellableOperation.value;
  }

  Future<dynamic> getTranslation(String query, String from, String to) async {
    return Future.delayed(const Duration(milliseconds: 1000), () {
      return "Hello";
    });
  }

关于文本更改的侦听器:

  onTextChanged() {
    fromCancelable(getTranslation("query", "EN", "TR")).then((value) {
      print("Then called: $value");
    });
  }

样本输出:

I/flutter ( 7312): Operation Cancelled
I/flutter ( 7312): Operation Cancelled
I/flutter ( 7312): Operation Cancelled
I/flutter ( 7312): Operation Cancelled
I/flutter ( 7312): Then called: Hello

【讨论】:

    【解决方案2】:

    有,叫定时器

    https://api.dartlang.org/stable/2.3.1/dart-async/Timer-class.html

    您可以延迟执行以及取消触发器。

    【讨论】:

      【解决方案3】:

      假设您使用TextField 作为输入,您可以调用getTranslation()onSubmitted 上,当用户完成编辑时会调用它:

       TextField(
         onSubmitted: (value) {
           getTranslation(value, 'en', 'ru'); 
         },
       );
      

      【讨论】:

      • 谢谢,但我需要在用户暂停输入时调用它,而不是在他明确提交查询时调用它。延迟只是为了防止为每个字符调用 api 并防止竞争条件。
      猜你喜欢
      • 2021-05-28
      • 2021-12-30
      • 1970-01-01
      • 2012-07-16
      • 1970-01-01
      • 2011-06-29
      • 1970-01-01
      • 2019-10-26
      相关资源
      最近更新 更多