【问题标题】:Can't update list with setState() in Flutter无法在 Flutter 中使用 setState() 更新列表
【发布时间】:2021-09-06 07:52:03
【问题描述】:

我有一个可以在 ListView 中显示的对象列表。现在我想实现一个搜索功能,只显示搜索结果。当我尝试在 TextField(甚至控制器)上使用 onChanged 时,它不起作用。我尝试调试,他正确更新了列表,但他没有更新小部件。但是,当我删除 onChanged 并添加一个按钮,然后调用我在 onChanged 上调用的相同方法时,一切正常。 目标是在用户在文本字段中写入时更新小部件。

我很乐意得到帮助

我的完整代码:

import 'package:flutter/material.dart';
import 'package:hello_fridge/single_ingredient_icon.dart';
import 'package:string_similarity/string_similarity.dart';
import 'entities/ingredient.dart';

class IngredientsContainer extends StatefulWidget {
  const IngredientsContainer({Key? key}) : super(key: key);

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

class _IngredientsContainerState extends State<IngredientsContainer> {
  late List<Ingredient> ingredients;
  final searchController = TextEditingController();

  @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    searchController.dispose();
    super.dispose();
  }

  void updateResults(String newValue) {
    if (newValue.isEmpty) {
      ingredients = Ingredient.getDummyIngredients();
    } else {
      print("new Value = $newValue");
      ingredients = this.ingredients.where((ing) {
        double similarity =
            StringSimilarity.compareTwoStrings(ing.name, newValue);
        print("$similarity for ${ing.name}");
        return similarity > 0.2;
      }).toList();
      ingredients.forEach((element) {
        print("found ${element.name}");
      });
    }
    setState(() {});
  }

  Widget _searchBar(List<Ingredient> ingredients) {
    return Row(
      children: <Widget>[
        IconButton(
          splashColor: Colors.grey,
          icon: Icon(Icons.restaurant),
          onPressed: null,
        ),
        Expanded(
          child: TextField(
            controller: searchController,
            onChanged: (newValue) {
              updateResults(newValue);
            },
            cursorColor: Colors.black,
            keyboardType: TextInputType.text,
            textInputAction: TextInputAction.go,
            decoration: InputDecoration(
                border: InputBorder.none,
                contentPadding: EdgeInsets.symmetric(horizontal: 15),
                hintText: "Search..."),
          ),
        ),
        Padding(
          padding: const EdgeInsets.only(right: 8.0),
          child: IconButton(
            icon: Icon(
              Icons.search,
              color: Color(0xff9ccc65),
            ),
            onPressed: () {
              updateResults(searchController.text);
            },
          ),
        ),
      ],
    );
  }

  @override
  void initState() {
    this.ingredients = Ingredient.getDummyIngredients();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Column(children: [
        Expanded(flex: 1, child: _searchBar(this.ingredients)),
        Expanded(flex: 4, child: IngredientsGrid(this.ingredients))
      ]),
    );
  }
}

class IngredientsGrid extends StatelessWidget {
  List<Ingredient> ingredients;

  IngredientsGrid(this.ingredients);

  List<Widget> _buildIngredients() {
    return this.ingredients.map((ing) => SingleIngredientIcon(ing)).toList();
  }

  // const IngredientsGrid({
  //   Key? key,
  // }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    this.ingredients.forEach((ing) => print(ing.name! + ","));
    return ListView(
      children: <Widget>[
        GridView.count(
            crossAxisCount: 4,
            // physics: NeverScrollableScrollPhysics(),
            // to disable GridView's scrolling
            shrinkWrap: true,
            // You won't see infinite size error
            children: _buildIngredients()),
        // ...... other list children.
      ],
    );
  }
}

此外,我不断收到此警告: “更改撰写区域内的内容可能会导致输入法行为异常,因此不鼓励使用。有关详细信息,请参阅https://github.com/flutter/flutter/issues/78827。”

访问链接的 GitHub 页面没有帮助

【问题讨论】:

    标签: flutter dart flutter-layout


    【解决方案1】:

    问题在于,虽然您正确过滤了列表,但您的 TextController 没有被分配任何值。

    因此,没有任何值被分配给您的 TextField 作为初始值,因此列表再次过滤以包含整个列表。

    要解决这个问题,只需像这样分配TextController newValue

    void updateResults(String newValue) {
     if (newValue.isEmpty) {
      ingredients = Ingredient.getDummyIngredients();
     } else {
      print("new Value = $newValue");
      ingredients = this.ingredients.where((ing) {
        double similarity =
            StringSimilarity.compareTwoStrings(ing.name, newValue);
        print("$similarity for ${ing.name}");
        return similarity > 0.2;
      }).toList();
      ingredients.forEach((element) {
        print("found ${element.name}");
      });
    }
    // change 
        searchController = TextEditingController.fromValue(
          TextEditingValue(
            text: newValue,
          ),
        );
    
    setState(() {});
    

    }

    如果抛出错误,则从变量声明中删除 final,如下所示:

    var searchController = TextEditingController();

    【讨论】:

    • 我使用 TextEditingController 来捕获 Textfield 值并在单击搜索按钮时使用它,效果很好。当从 TextField 的 onChanged 属性调用时,这里不起作用的是相同的方法。我尝试添加你给我的代码块,除了光标的奇怪行为之外没有任何变化(它在我写的每个字符后面,所以字符串以相反的方式编写)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-07
    • 2020-12-17
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 2022-07-23
    相关资源
    最近更新 更多