Flutter中ListView.Builder添加列表项不显示问题求助
问题解决:Flutter ListView.Builder 新增项不显示
核心问题分析
- 未触发状态更新:添加新数据后没有调用
setState(() {}),Flutter无法感知数据变化,不会重新构建UI。 - build方法内重复添加初始数据:每次组件build时都会执行
widget._transferencias.add(...),导致数据重复累加,逻辑混乱。 - 手动维护长度变量易出错:自己定义的
tamanho变量和实际列表长度可能不同步,应该直接使用列表的length属性。 - 数据存储位置不规范:列表数据放在
StatefulWidget类中,更合理的做法是放在对应的State类里,便于状态管理。
修复步骤
- 将列表数据移到
ListaTransferenciasState类中,避免直接操作widget的成员变量。 - 在
initState中初始化初始数据,确保只执行一次。 - 添加新项时调用
setState,通知Flutter更新UI。 - 移除手动维护的
tamanho变量,直接用列表的length作为ListView.builder的itemCount。
修改后的完整代码
import 'package:flutter/material.dart'; void main() => runApp(BytebankApp()); class BytebankApp extends StatelessWidget { BytebankApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: ListaTransferencias(), ), ); } } class FormularioTransferencia extends StatelessWidget { final TextEditingController _controladorCampoNumeroConta = TextEditingController(); final TextEditingController _controladorCampoValor = TextEditingController(); FormularioTransferencia({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Criando Transferência'), ), body: Column( children: <Widget>[ Editor( controlador: _controladorCampoNumeroConta, rotulo: 'Numero da conta', dica: '0000', ), Editor( controlador: _controladorCampoValor, rotulo: 'Valor', dica: '0.00', icone: Icons.monetization_on, ), ElevatedButton( onPressed: () => _criaTransferencia(context), child: Text('Confirmar'), ) ], )); } void _criaTransferencia(BuildContext context) { final int? numeroConta = int.tryParse(_controladorCampoNumeroConta.text); final double? valor = double.tryParse(_controladorCampoValor.text); if (numeroConta != null && valor != null) { final transferenciaCriada = Transferencia(valor, numeroConta); debugPrint('Criando transferencia'); debugPrint('$transferenciaCriada'); Navigator.pop(context, transferenciaCriada); } } } class Editor extends StatelessWidget { final TextEditingController controlador; final String rotulo; final String dica; final IconData? icone; Editor( {super.key, required this.controlador, required this.rotulo, required this.dica, this.icone}); @override Widget build(BuildContext context) { return Padding( padding: EdgeInsets.all(16.0), child: TextField( controller: controlador, style: TextStyle(fontSize: 24.0), decoration: InputDecoration( icon: icone != null ? Icon(icone) : null, labelText: rotulo, hintText: dica, ), keyboardType: TextInputType.number, ), ); } } class ListaTransferencias extends StatefulWidget { @override State<StatefulWidget> createState() { return ListaTransferenciasState(); } } class ListaTransferenciasState extends State<ListaTransferencias> { final List<Transferencia> _transferencias = <Transferencia>[]; @override void initState() { super.initState(); // 初始化数据,只执行一次 _transferencias.addAll([ Transferencia(200.0, 2000), Transferencia(300.0, 3000), Transferencia(400.0, 4000), Transferencia(500.0, 5000), ]); } @override Widget build(BuildContext context) { debugPrint('Tamanho atual: ${_transferencias.length}'); return Scaffold( appBar: AppBar( title: Text('Transferências'), ), body: ListView.builder( itemCount: _transferencias.length, itemBuilder: (context, indice) { final transferencia = _transferencias[indice]; return ItemTransferencia(transferencia); }, ), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () { final Future<Transferencia?> future = Navigator.push(context, MaterialPageRoute(builder: (context) { return FormularioTransferencia(); })); future.then((transferenciaRecebida) { if (transferenciaRecebida == null) return; debugPrint('chegou no then do future'); debugPrint('$transferenciaRecebida'); // 调用setState触发UI更新 setState(() { _transferencias.add(transferenciaRecebida); }); debugPrint('Novo tamanho: ${_transferencias.length}'); }); }, ), ); } } class ItemTransferencia extends StatelessWidget { final Transferencia _transferencia; ItemTransferencia(this._transferencia, {super.key}); @override Widget build(BuildContext context) { return Card( child: ListTile( leading: Icon(Icons.monetization_on), title: Text(_transferencia.valor.toString()), subtitle: Text(_transferencia.numeroConta.toString()), )); } } class Transferencia { final double valor; final int numeroConta; Transferencia(this.valor, this.numeroConta); @override String toString() { return 'Transferencia{valor: $valor, numeroConta: $numeroConta}'; } }
关键修改点说明
- 把
_transferencias列表从ListaTransferencias(StatefulWidget)移到ListaTransferenciasState中,符合Flutter状态管理的规范。 - 在
initState中初始化初始数据,避免每次build都重复添加。 - 添加新项时,用
setState包裹添加操作,强制Flutter重新构建UI,更新ListView。 - 移除了手动维护的
tamanho变量,直接使用_transferencias.length作为itemCount,保证数据和UI长度一致。
内容的提问来源于stack exchange,提问作者Gabriel Dodd
相关产品推荐
相关产品推荐

