Dart: cancelable post delay / future

余生颓废 提交于 2019-12-11 04:56:19

问题


I am new to flutter and I want to translate some text from an InputField by calling an API. However I don't want to call it on every key stroke, but instead only when the user paused typing.

On Android I would just use the Handler class with postDelay() with beforehand calling removeAllCallbacksAndMessages(null). Is there a way to do something similar on Dart?

Here is my current code:

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)
    });
  }

Edit 1

I'm calling the code from my Bloc like so:

@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));
  }

This is why I cannot call .then() on the future because I wouldn't be able to yield the new state from the block of the nested function.

Any help is appreciated!


回答1:


You can achieve cancelling the Future async operation by using CancelableOperation.

Here is an example (p.s I simplified your method signature for me to test it easily)

  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";
    });
  }

On Text Changed Listener:

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

Sample output:

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:


Yes there is, it is called Timer

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

You can delay execution as well as cancel the trigger.




回答3:


Assuming that you're using a TextField for your input, you can call getTranslation() on the onSubmitted, which will be called when the user finishes editing :

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


来源:https://stackoverflow.com/questions/56345983/dart-cancelable-post-delay-future

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!