我有一个Textfield、一个搜索按钮和一个ListView.Builder.当我点击搜索按钮时,系统会请求获取一些数据,并将其放入列表中.我希望ListView使用我们发回的数据进行更新,但这并没有发生.我认为问题是setState个唯一的工作在树下,这两个小部件在不同的子树中.对吗?也许我需要更改小部件的 struct 才能使其正常工作?

void _updateLocationOptions(List<Location> locations) {
  locationOptions.clear();
  locationOptions = locationOptions.toList();
  setState(() {
    locationOptions = locations;
  });
}

Column(
  crossAxisAlignment: CrossAxisAlignment.end,
  children: [
    Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Expanded(
          child: TextFormField(
            key: const ValueKey("locationField"),
            
            onChanged: (String value) {
              setState(() {
                locationFieldController.text = value;
              });
            },
          ),
        ),
        IconButton(
          onPressed: () async {
            final res = await eventsRepo.fetchLocationOptions(client, locationFieldController.text);
            _updateLocationOptions(res);
            print("locationOptions: $locationOptions"); // Correct value
          },
          icon: const Icon(Icons.search),
        ),
      ],
    ),
    ListView.builder(
      shrinkWrap: true,
      itemCount: locationOptions.length,
      itemBuilder: (BuildContext context, int index) {
        if (locationOptions.isEmpty) {
          return null;
        }
        return Text(locationOptions[index].name!);
      },
    ),
  ],
),

如果我执行热重新加载,我可以获得要在屏幕上显示的正确数据,但不会自动显示所需的数据.

推荐答案

底部工作表的构建器回调中的小部件不会反映从调用showBottomSheet的位置的State开始的状态变化.您必须将底部工作表小部件提取到它自己的StatefulWidget.

例如,此代码won't work:

import 'package:flutter/material.dart';

class AnotherScreen extends StatefulWidget {
  const AnotherScreen({super.key});

  @override
  State<AnotherScreen> createState() => _AnotherScreenState();
}

class _AnotherScreenState extends State<AnotherScreen> {
  bool isActive = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Another Screen'),
      ),
      body: Center(
        child: FilledButton(
          onPressed: () {
            showModalBottomSheet(
              context: context,
              builder: (context) {

                // The widget returned here won't reflect state changes
                return Container(
                  padding: EdgeInsets.all(20),
                  child: Column(
                    children: [
                      FilledButton(
                        onPressed: () {
                          setState(() {
                            isActive = !isActive;
                          });
                        },
                        child: Text('Toggle'),
                      ),
                      Text(isActive ? 'Active' : 'Inactive'),
                    ],
                  ),
                );
              },
            );
          },
          child: Text('Show Bottom Sheet'),
        ),
      ),
    );
  }
}

但这个代码works:

import 'package:flutter/material.dart';

class AnotherScreen extends StatefulWidget {
  const AnotherScreen({super.key});

  @override
  State<AnotherScreen> createState() => _AnotherScreenState();
}

class _AnotherScreenState extends State<AnotherScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Another Screen'),
      ),
      body: Center(
        child: FilledButton(
          onPressed: () {
            showModalBottomSheet(
              context: context,
              builder: (context) {

                // The widget is now extracted to its own StatefulWidget
                return BottomSheetWidget();
              },
            );
          },
          child: Text('Show Bottom Sheet'),
        ),
      ),
    );
  }
}

class BottomSheetWidget extends StatefulWidget {
  const BottomSheetWidget({super.key});

  @override
  State<BottomSheetWidget> createState() => _BottomSheetWidgetState();
}

class _BottomSheetWidgetState extends State<BottomSheetWidget> {
  bool isActive = true;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20),
      child: Column(
        children: [
          FilledButton(
            onPressed: () {
              setState(() {
                isActive = !isActive;
              });
            },
            child: Text('Toggle'),
          ),
          Text(isActive ? 'Active' : 'Inactive'),
        ],
      ),
    );
  }
}

Flutter相关问答推荐

如何在SingleChildScrollView中使用GridView

滚动时应用栏 colored颜色 更改Flutter

如何更新文本字段的基础上的选定下拉菜单?

Android Emulator冻结,但在调整窗口大小时解冻

MobX Build_Runner问题:不生成.G文件(Flutter )

如何防止onTapCancel由子元素触发?

如何在抖动中预加载一条路由,或者即使在屏幕外也保持加载小工具?

在Fighter中,我如何在窗口的顶部和底部排列Widget?

为什么当我使用Riverpod更新状态时,列表会被刷新?

Flutter :在后台实现振动

BottomNavigationBar-我应该使用Container和Align吗?

我怎样才能在Ffltter中显示html布局链接?

使用 Firebase Realtime 实现高效流式传输

在带有 flutter 的 Native Android 中,EventChannel.EventSink 始终为 null

Flutter firebase_auth 和 firebase_core 依赖错误

Flutter RIverpod 奇怪地改变状态

更改文本字段Flutter 中最大字母的 colored颜色

Flutter:如何将列表转换为字符串?

在另一个页面编辑数据后更新 Flutter 页面的惯用方法?

如何在 IntroductionScreen 小部件 Flutter 中制作全屏渐变色