有没有办法在用户停止打字后发送请求?

问题描述 投票:0回答:2
  • 我正在寻找一种在用户停止输入 X 秒后发送 API 请求的方法。
  • 我发送请求的方式是通过 onTextChanged 回调,但是,每次按键时都会发送一个请求
  • 我已经看到了在 React 中使用超时来做到这一点的方法,但是,我对 flutter 还比较陌生,所以任何帮助将不胜感激
search dart flutter
2个回答
48
投票

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

此代码使用Debouonce方法来实现该功能。 去抖动的工作原理是确保函数仅在自上次调用以来经过一定时间后才执行。如果在该时间段过去之前再次调用该函数,则先前的调用将被取消,并且计时器将被重置。这可以确保该函数不会执行得太频繁。

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 ....'
                ),
            );
    }
}

6
投票

在 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(),
          ],
        ),
      ),
    );
  }
}

您可以在以下Norbert Kozsir 的文章和代码中看到此代码的实际运行

© www.soinside.com 2019 - 2024. All rights reserved.