flutter - 如何在 Dart 中对 Textfield onChange 进行去抖动?

标签 flutter dart textfield onchange debouncing

我正在尝试开发一个 TextField,它可以在 Firestore 数据库中的数据发生更改时更新它们。它似乎有效,但我需要防止 onChange 事件多次触发。

在 JS 中我会使用 lodash _debounce() 但在 Dart 中我不知道该怎么做。我读过一些去抖动库,但我不知道它们是如何工作的。

这是我的代码,它只是一个测试,所以可能有些奇怪:

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


class ClientePage extends StatefulWidget {

  String idCliente;


  ClientePage(this.idCliente);

  @override
  _ClientePageState createState() => new _ClientePageState();

  
}

class _ClientePageState extends State<ClientePage> {

  TextEditingController nomeTextController = new TextEditingController();


  void initState() {
    super.initState();

    // Start listening to changes 
    nomeTextController.addListener(((){
        _updateNomeCliente(); // <- Prevent this function from run multiple times
    }));
  }


  _updateNomeCliente = (){

    print("Aggiorno nome cliente");
    Firestore.instance.collection('clienti').document(widget.idCliente).setData( {
      "nome" : nomeTextController.text
    }, merge: true);

  }



  @override
  Widget build(BuildContext context) {

    return new StreamBuilder<DocumentSnapshot>(
      stream: Firestore.instance.collection('clienti').document(widget.idCliente).snapshots(),
      builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
        if (!snapshot.hasData) return new Text('Loading...');

        nomeTextController.text = snapshot.data['nome'];


        return new DefaultTabController(
          length: 3,
          child: new Scaffold(
            body: new TabBarView(
              children: <Widget>[
                new Column(
                  children: <Widget>[
                    new Padding(
                      padding: new EdgeInsets.symmetric(
                        vertical : 20.00
                      ),
                      child: new Container(
                        child: new Row(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          children: <Widget>[
                            new Text(snapshot.data['cognome']),
                            new Text(snapshot.data['ragionesociale']),
                          ],
                        ),
                      ),
                    ),
                    new Expanded(
                      child: new Container(
                        decoration: new BoxDecoration(
                          borderRadius: BorderRadius.only(
                            topLeft: Radius.circular(20.00),
                            topRight: Radius.circular(20.00)
                          ),
                          color: Colors.brown,
                        ),
                        child: new ListView(
                          children: <Widget>[
                            new ListTile(
                              title: new TextField(
                                style: new TextStyle(
                                  color: Colors.white70
                                ),
                                controller: nomeTextController,
                                decoration: new InputDecoration(labelText: "Nome")
                              ),
                            )
                          ]
                        )
                      ),
                    )
                  ],
                ),
                new Text("La seconda pagina"),
                new Text("La terza pagina"),
              ]
            ),
            appBar: new AppBar(
              title: Text(snapshot.data['nome'] + ' oh ' + snapshot.data['cognome']),
              bottom: new TabBar(          
                tabs: <Widget>[
                  new Tab(text: "Informazioni"),  // 1st Tab
                  new Tab(text: "Schede cliente"), // 2nd Tab
                  new Tab(text: "Altro"), // 3rd Tab
                ],
              ),
            ),
          )
        );
        
      },
    );

    print("Il widget id è");
    print(widget.idCliente);
    
  }
}

最佳答案

实现

导入依赖:

import 'dart:async';

在您的小部件状态中声明一个计时器:

Timer? _debounce;

添加监听方法:

_onSearchChanged(String query) {
    if (_debounce?.isActive ?? false) _debounce.cancel();
    _debounce = Timer(const Duration(milliseconds: 500), () {
        // do something with query
    });
    }

别忘了清理:

@override
void dispose() {
    _debounce?.cancel();
    super.dispose();
}

用法

在你的构建树 Hook onChanged 事件:

child: TextField(
        onChanged: _onSearchChanged,
        // ...
    )

关于flutter - 如何在 Dart 中对 Textfield onChange 进行去抖动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51791501/

相关文章:

Flutter - 'the property ' 设置'无法无条件访问,因为接收器可以是 'null' '

dart - 为什么我的更新的可观察列表未反射(reflect)在模板中?

forms - 如何从另一个屏幕重置 Flutter 中的表单?

swift - 如何将文本字段添加到新根下的firebase?

swift - 使用 swift 自定义 TextField 图层/背景/适应

image - 在 Flutter 应用程序中添加 360 VR 照片查看器

json - 如何在 json_serializable flutter 中将 int 时间戳转换为 DateTime

dart - 断言语句在 dart 2 中不再有用吗?

swift - 第一次向文本字段添加文本 [Swift]

android - Flutter 中不同的屏幕尺寸和 dpi 缩放比例