用户停止键入后,是否可以发送请求?

时间:2018-11-04 22:29:17

标签: search dart flutter

  • 我正在寻找一种在用户停止输入X秒钟后发送API请求的方法。
  • 我发送请求的方式是通过onTextChanged回调,但是,该回调在每次按键时都会发送一个请求
  • 我在React中已经看到了解决超时的方法,但是,我比较陌生,所以我们将不胜感激

2 个答案:

答案 0 :(得分:2)

在Flutter中执行此操作的通常方法是使用RxDart及其debounce()方法。允许在启动特定呼叫之前等待一小段时间。

在下面的完整示例中,您将看到它在1秒钟的时间内起作用。在该示例中,显示了一条消息,其中应调度对服务器的调用。

import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final subject = new PublishSubject<String>();

  bool isLoading = false;

  GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey();

  void _textChanged(String text) {
    if (text.isEmpty) {
      setState(() {
        isLoading = false;
      });
      return;
    }
    setState(() {
      isLoading = true;
    });
    scaffoldKey.currentState.showSnackBar(new SnackBar(
      content: new Text("Search for ${text}"),
    ));
  }

  @override
  void initState() {
    super.initState();
    subject.stream.debounce(new Duration(milliseconds: 1000)).listen(_textChanged);
  }

  @override
  void dispose() {
    subject.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: scaffoldKey,
      appBar: new AppBar(
        title: new Text("Debounce demo"),
      ),
      body: new Container(
        padding: new EdgeInsets.all(8.0),
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            new TextField(
              decoration: new InputDecoration(
                hintText: 'Type text to search',
              ),
              onChanged: (string) => (subject.add(string)),
            ),
            isLoading
                ? Padding(
                    padding: const EdgeInsets.all(20.0),
                    child: new CircularProgressIndicator(),
                  )
                : new Container(),
          ],
        ),
      ),
    );
  }
}

您可以在以下article and code by Norbert Kozsir

中查看此代码的运行情况

答案 1 :(得分:1)

您可以使用以下代码执行此操作:

import 'package:flutter/material.dart';
import 'dart:async';

class Test extends StatefulWidget {
    @override
    State<StatefulWidget> createState() {
        return _TestState();
    }
}

class _TestState extends State<StatefulWidget> {
    Timer searchOnStoppedTyping;

    _onChangeHandler(value ) {
        const duration = Duration(milliseconds:800); // set the duration that you want call search() after that.
        if (searchOnStoppedTyping != null) {
            setState(() => searchOnStoppedTyping.cancel()); // clear timer
        }
        setState(() => searchOnStoppedTyping = new Timer(duration, () => search(value)));
    }

    search(value) {
        print('hello world from search . the value is $value');
    }
    @override
    Widget build(BuildContext context) {
        return TextField(
            onChanged: _onChangeHandler,
            decoration: InputDecoration(
                hintText: 'Search ....'
                ),
            );
    }
}