Flutter Dart网络数据获取问题:输入编码后数据不显示
问题分析与修复方案
核心问题
- 异步请求未等待:
fetchData是异步方法,点击按钮后直接调用showFetchedData,此时数据还未完成获取,弹窗展示的是空列表。 - 未触发UI更新:数据获取成功后没有调用
setState(),页面中的列表组件无法感知数据变化,不会自动刷新。 - 错误无提示:异步请求的异常未被捕获,无法排查请求失败或数据解析问题。
- 键名匹配风险:需确认API返回的字段是否为
'next bus'(带空格),若后端返回驼峰/下划线格式(如nextBus/next_bus),会导致文本显示为空。
修复步骤与代码修改
1. 等待异步请求完成
将按钮点击事件改为异步方法,确保数据获取完成后再打开弹窗:
onPressed: () async { final query = queryController.text.trim(); if (query.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请输入公交服务编码')), ); return; } try { await fetchData(query); showFetchedData(); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('请求失败: $e')), ); } },
2. 获取数据后更新UI
在fetchData中调用setState(),触发页面组件刷新:
Future<void> fetchData(String query) async { final response = await http.get( Uri.parse('https://laravelsyd-fypfinalver.herokuapp.com/getBusService?query=$query') ); if (response.statusCode == 200) { final List<dynamic> data = json.decode(response.body); setState(() { dataList = List<Map<String, dynamic>>.from(data); }); } else { throw Exception('HTTP请求失败,状态码: ${response.statusCode}'); } }
3. 增加字段空值处理
避免因键名不匹配导致显示异常,增加空值判断:
return ListTile( title: Text('Service: ${item['service'] ?? 'N/A'}'), subtitle: Text('Next Bus: ${item['next bus'] ?? 'N/A'}'), );
完整修改代码
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: BusNearby(), ); } } // 类名遵循大驼峰命名规范 class BusNearby extends StatefulWidget { const BusNearby({super.key}); @override _BusNearbyState createState() => _BusNearbyState(); } class _BusNearbyState extends State<BusNearby> { final TextEditingController queryController = TextEditingController(); List<Map<String, dynamic>> dataList = []; Future<void> fetchData(String query) async { final response = await http.get( Uri.parse('https://laravelsyd-fypfinalver.herokuapp.com/getBusService?query=$query') ); if (response.statusCode == 200) { final List<dynamic> data = json.decode(response.body); setState(() { dataList = List<Map<String, dynamic>>.from(data); }); } else { throw Exception('HTTP请求失败,状态码: ${response.statusCode}'); } } void showFetchedData() { showModalBottomSheet( context: context, builder: (BuildContext modalContext) { return Container( padding: const EdgeInsets.all(16), child: dataList.isEmpty ? const Center(child: Text('未找到对应数据')) : ListView.builder( itemCount: dataList.length, itemBuilder: (_, index) { final item = dataList[index]; return ListTile( title: Text('Service: ${item['service'] ?? 'N/A'}'), subtitle: Text('Next Bus: ${item['next bus'] ?? 'N/A'}'), ); }, ), ); }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Data Retrieval Example'), ), body: Center( child: Column( children: <Widget>[ Padding( padding: const EdgeInsets.all(16.0), child: TextField( controller: queryController, decoration: const InputDecoration( labelText: 'Enter Bus Service Code', ), ), ), ElevatedButton( onPressed: () async { final query = queryController.text.trim(); if (query.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请输入公交服务编码')), ); return; } try { await fetchData(query); showFetchedData(); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('请求失败: $e')), ); } }, child: const Text('Fetch Data'), ), if (dataList.isNotEmpty) SizedBox( width: 200, height: 100, child: ListView.builder( itemCount: dataList.length, itemBuilder: (context, index) { final item = dataList[index]; return ListTile( title: Text('Service: ${item['service'] ?? 'N/A'}'), subtitle: Text('Next Bus: ${item['next bus'] ?? 'N/A'}'), ); }, ), ), const DataTable( columns: <DataColumn>[ DataColumn(label: Text('Service Code')), DataColumn(label: Text('Location')), ], rows: <DataRow>[ DataRow(cells: <DataCell>[ DataCell(Text('1076')), DataCell(Text('Larkin Terminal')), ]), DataRow(cells: <DataCell>[ DataCell(Text('1084')), DataCell(Text('Taman Universiti')), ]), DataRow(cells: <DataCell>[ DataCell(Text('1019')), DataCell(Text('Skudai Prade')), ]), DataRow(cells: <DataCell>[ DataCell(Text('1052')), DataCell(Text('Opposite Skudai Prade')), ]), ], ), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者katamykenji
相关产品推荐
相关产品推荐

