Flutter使用setState时列表不更新及参数传递优化问题
问题修复方案
一、搜索过滤失效问题解决
你代码中搜索不生效的核心原因是错误重写了setState方法而非调用框架自带的setState触发UI更新:你在_runFilter内部定义了一个带有@override的局部setState方法,这个方法不会被自动执行,resultCities更新后UI无法重绘,因此列表永远展示初始数据。
二、State构造传参优化
Flutter官方不推荐通过State构造函数传递参数,State类可以直接通过widget属性访问所属StatefulWidget的所有公开成员,直接调用widget.cities即可拿到城市列表,不需要手动传参。
三、完整修正后代码
import 'package:flutter/material.dart'; import 'package:passenger_flutter_app/models/new_city.dart'; import 'package:passenger_flutter_app/models/origin_destination.dart'; import 'package:passenger_flutter_app/utils/colors.dart'; class SelectionScreen extends StatefulWidget { final List<OriginDestination>? cities; const SelectionScreen({super.key, this.cities}); @override _SelectionScreenState createState() => _SelectionScreenState(); } class _SelectionScreenState extends State<SelectionScreen> { bool originSelected = false; List<OriginDestination> resultCities = []; void getCitiesFromResponse() { resultCities = widget.cities ?? []; } @override void initState() { getCitiesFromResponse(); super.initState(); } void _runFilter(String enteredKeyword) { List<OriginDestination> tempList = []; if (enteredKeyword.trim().isEmpty) { tempList = widget.cities ?? []; } else { tempList = widget.cities! .where((city) => city.origin?.name?.toLowerCase() .contains(enteredKeyword.toLowerCase()) ?? false) .toList(); } setState(() { resultCities = tempList; }); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: const Color(0xffEEEDEF), body: Column( children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 10.0), child: Column( children: [ Container( width: MediaQuery.of(context).size.width * 0.8, ), Row( children: [ IconButton( icon: const Icon(Icons.arrow_back), color: Colors.orange, onPressed: () { Navigator.pop(context); }, ), Column( children: [ originSelected == true ? const SizedBox.shrink() : Container( width: MediaQuery.of(context).size.width * 0.85, height: 50.0, decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all( Radius.circular(5.0)), border: Border.all(color: colorAccent)), child: TextField( decoration: InputDecoration( hintText: "Enter Origin", border: InputBorder.none, contentPadding: const EdgeInsets.only(left: 10.0), hintStyle: TextStyle( fontSize: 15.0, color: Colors.grey[500], ), ), onChanged: (value) { _runFilter(value); }, ), ), ], ), ], ), ], ), ), Align( alignment: Alignment.centerLeft, child: Padding( padding: EdgeInsets.only( left: MediaQuery.of(context).size.width * 0.04, top: 3.0), child: Text( '热门搜索:', style: TextStyle( color: popUpLightTextColor, fontSize: MediaQuery.of(context).size.width * 0.035), ), ), ), Expanded( child: ListView.builder( itemCount: resultCities.length, itemBuilder: (context, index) { return Padding( padding: EdgeInsets.only( left: 18.0, top: index == 0 ? 29.0 : 15.0, bottom: 15.0), child: InkWell( onTap: () { print(resultCities[index].origin?.name); /* 原有选中逻辑保留即可 setState(() { widget.city=filteredCities[index]['city']; print("已修改为 - "); Navigator.pop(context); });*/ }, child: Text( resultCities[index].origin?.name ?? "无名称", style: const TextStyle( color: darkText, fontSize: 15.0, fontWeight: FontWeight.normal, ), ), ), ); }, ), ), ], ), ), ); } }
优化点说明
- 删掉了冗余的
_allCities、filteredCities变量,减少内存占用 - 修复了
setState调用逻辑,过滤后自动刷新UI - 去掉了State构造传参的不合理写法,直接通过
widget.cities获取父组件参数 - 空安全判断优化,避免空指针异常
- 删掉了build方法中重复定义的
originSelected局部变量,避免逻辑覆盖
内容的提问来源于stack exchange,提问作者Shreyansh Sharma
相关产品推荐
相关产品推荐

