Flutter AutoCompleteTextField建议未显示更新的建议

时间:2019-07-06 03:21:49

标签: flutter

我正在使用Flutter创建一个使用AutoCompleteTextField autocomplete_textfield: ^1.7.3的应用程序。我对此小部件有问题。在开始之前,让我解释一下我对这个小部件的理解。

它获取“建议”列表,并为建议列表中的每个条目构建列表项。当用户在文本字段中键入内容时,它会与项目过滤器匹配并显示类似的项目。

我遇到的问题是,此建议列表未从setState()中得到更新。我有一个数据库可从中获取数据,我尝试在覆盖的initState()处异步获取数据,但是即使记录了列表的长度,建议也没有出现。类似的问题here。我觉得,一旦构建了窗口小部件,此“建议”列表就永远不会像有状态窗口小部件那样刷新。我在Google上搜索了这些内容,并找到了FutureBuilder小部件的变通办法,并且此举得以完成(目前)。我在这里粘贴了我的有效代码。

import 'package:autocomplete_textfield/autocomplete_textfield.dart';
import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';

class AddKeptPlaceScreen extends StatefulWidget {
  static const String route = "/add_kept_place";

  @override
  _AddKeptPlaceScreenState createState() => _AddKeptPlaceScreenState();
}

class _AddKeptPlaceScreenState extends State<AddKeptPlaceScreen> {
  bool _hasAKeptPlace = false;
  bool disableKeptPlaceSwitch = false;
  int _keptPlaceKeptPlaceID;
  List<KeptPlaceModal> listOfKeptPlaces = new List();

  TextEditingController _keptPlaceKeptPlace = new TextEditingController();

  GlobalKey<AutoCompleteTextFieldState<KeptPlaceModal>> keyK =
      new GlobalKey<AutoCompleteTextFieldState<KeptPlaceModal>>();

  void clearAllFields(KeptPlaceModal place) {
    _keptPlaceKeptPlace.text = "";
    setState(() {
      this._keptPlaceKeptPlaceID = null;
    });
  }

  Widget addKeptPlace(BuildContext context, String imagePath) {
    return new Scaffold(
        floatingActionButton: SpeedDial(
          closeManually: false,
          child: Icon(Icons.image),
          children: [
            SpeedDialChild(
                backgroundColor: Colors.blueAccent,
                child: Icon(Icons.add_photo_alternate),
                label: Strings.fab_pick_picture,
                onTap: () {
                  handlePictureButton(false);
                }),
          ],
        ),
        body: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
                child: Row(
                  children: <Widget>[
                    AbsorbPointer(
                      child: Switch(
                        value: this._hasAKeptPlace,
                        activeColor: Colors.black,
                        onChanged: (bool valueChanged) {
                          setState(() {
                            _keptPlaceKeptPlace.text = "";
                            _keptPlaceKeptPlaceID = null;
                            this._hasAKeptPlace = valueChanged;
                          });
                        },
                      ),
                      absorbing: disableKeptPlaceSwitch,
                    ),
                    Flexible(
                      child: AbsorbPointer(
                        absorbing: !_hasAKeptPlace,
                        child: AutoCompleteTextField<KeptPlaceModal>(
                          clearOnSubmit: false,
                          controller: _keptPlaceKeptPlace,
                          onFocusChanged: (changed) {
                            setState(() {
                              this.disableKeptPlaceSwitch = changed;
                            });
                            validateAutoInputs(
                                this.listOfKeptPlaces, _keptPlaceKeptPlace);
                          },
                          textCapitalization: TextCapitalization.words,
                          decoration: InputDecoration(
                              labelText: "Kept Place",
                              labelStyle: TextStyle(color: Colors.pink),
                              border: OutlineInputBorder()),
                          style: TextStyle(color: Colors.black),
                          itemBuilder: (context, item) {
Note here ----------------> print(listOfKeptPlaces.length);
                            return AutoCompleteEntry(
                              entryImage: item.keptPlaceImage,
                              entryTitle: item.keptPlaceName,
                            );
                          },
                          suggestionsAmount: 4,
                          itemFilter: (item, query) {
                            return item.keptPlaceName
                                .toLowerCase()
                                .contains(query.toLowerCase());
                          },
                          itemSorter: (a, b) {
                            return a.keptPlaceName.compareTo(b.keptPlaceName);
                          },
                          itemSubmitted: (item) {
                            setState(() {
                              _keptPlaceKeptPlace.text = item.keptPlaceName;
                              _keptPlaceKeptPlaceID = item.keptPlaceID;
                            });
                          },
                          suggestions: this.listOfKeptPlaces,
                          key: keyK,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
              Padding(
                padding: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 5.0),
                child: ConstrainedBox(
                    constraints: BoxConstraints(
                        minWidth: MediaQuery.of(context).size.width - 20),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        RaisedButton(
                          onPressed: () {
                            // Create a "keptPlace" item and insert into db
                              createNewKeptPlace(keptPlace).then((v) {
                                clearAllFields(keptPlace);
                                print("Done");
                              }).catchError((error) {
                                print(error);
                              });
                            } else {
                              print("Empty");
                            }
                          },
                          color: Colors.green,
                          child: Text(
                            "Save",
                            style: TextStyle(color: Colors.white),
                          ),
                        ),
                        Padding(
                          padding: EdgeInsets.all(5.0),
                        ),
                        RaisedButton(
                          onPressed: () {
                            clearAllFields(null);
                          },
                          color: Colors.pinkAccent,
                          child: Text(
                            "Clear",
                            style: TextStyle(color: Colors.white),
                          ),
                        ),
                      ],
                    )),
              )
            ],
          ),
        ));
  }

  @override
  Widget build(BuildContext context) {
    // Future method to fetch data from database and load state variables. But
    // as we are using FutureBuilder, make sure not to call setState as it will
    // cause infinite loop of widget building
    Future<bool> loadKeptPlacesFromDB() async {
      List<KeptPlaceModal> _keptPlaceList = await getKeptPlaceList();
      this.listOfKeptPlaces = _keptPlaceList;
      return true;
    }

    Widget addKeptPlaceView() {
      return new Scaffold(
        appBar: new AppBar(
          title: Text("Add Kept Place"),
        ),
        body: new Container(
          child: new Center(
            child: addKeptPlace(context, null),
          ),
        ),
      );
    }

    return new FutureBuilder(
        future: loadKeptPlacesFromDB(),
        builder: (BuildContext buildContext, AsyncSnapshot snapshot) {
          if (snapshot.hasData) {
            return addKeptPlaceView();
          } else {
            return Scaffold(
              body: Center(child: CircularProgressIndicator()),
            );
          }
        });
  }
}

现在,我想动态更新“建议”列表;从同一个窗口。那就是在用户单击“保存”按钮时将一个项目添加到列表中。因此,当他再次输入而又不导航时,新项目应出现在建议列表中。我尝试了很多事情;

  1. 将项目插入数据库以更新列表后,调用setState()
  2. 调用了空白的setState(){}并登录以查看是否再次构建了父方法,并且确实可以构建
  3. 不使用setState()直接更新列表

对于上述每个方法,我在AutoCompleteTextField构建器方法中放置了一个print(),以查看listOfKeptPlaces中有多少个项目,并且似乎增加了,并且该项目在那里(类型和所有内容都相同),但是新的该项目未显示在建议列表中。这与我之前使我使用FutureBuilder而不是使用initState()方法填充列表的问题类似。

我在这里使用状态正确吗?我的代码或小部件中是否存在错误?感谢您提前提出的提示:)

0 个答案:

没有答案