You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中ListView.Builder添加列表项不显示问题求助

问题解决:Flutter ListView.Builder 新增项不显示

核心问题分析

  1. 未触发状态更新:添加新数据后没有调用setState(() {}),Flutter无法感知数据变化,不会重新构建UI。
  2. build方法内重复添加初始数据:每次组件build时都会执行widget._transferencias.add(...),导致数据重复累加,逻辑混乱。
  3. 手动维护长度变量易出错:自己定义的tamanho变量和实际列表长度可能不同步,应该直接使用列表的length属性。
  4. 数据存储位置不规范:列表数据放在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 18:07:07