Flutter中API数据已获取但ListView不显示,求问题排查
API返回正常但ListView无法显示数据
我正在尝试将API返回的数据展示在ListView中,已通过控制台确认API返回200成功响应且数据正常,但UI界面无法显示数据。想请教是否存在遗漏或代码错误,以下是我的实现代码:
API请求代码
class ListDosenProvider extends ChangeNotifier { static Future<List<ModelDosen>> getDosen() async { String url = Constant.baseURL; String token = await UtilSharedPreferences.getToken(); final response = await http.get( Uri.parse( '$url/auth/mhs_siakad/dosen', ), headers: { 'Authorization': 'Bearer $token', }, ); print(response.statusCode); print(response.body); if (response.statusCode == 200) { final List result = json.decode(response.body); return result.map((e) => ModelDosen.fromJson(e)).toList(); // return ModelDosen.fromJson(jsonDecode(response.body)); } else { throw Exception(); } } }
Widget调用代码
import 'package:flutter/material.dart'; import '../../../models/dosen/dosen_model.dart'; import '../../../provider/dosen/dosen_provider.dart'; import '../../../theme.dart'; import '../../../widgets/custom_appbar.dart'; class DosenPage extends StatefulWidget { const DosenPage({super.key}); @override State<DosenPage> createState() => _DosenPageState(); } class _DosenPageState extends State<DosenPage> { List<Datum> data = []; // @override // void initState() { // super.initState(); // fetchData(); // } // fetchData() async { // final apiResponse = await ListDosenProvider().getDosen() ??; // setState(() { // data = (apiResponse.data!); // }); // } @override Widget build(BuildContext context) { return Scaffold( appBar: PreferredSize( preferredSize: const Size.fromHeight(kToolbarHeight), child: CustomAppbar( title: 'Dosen', ), ), body: Center( child: FutureBuilder<List<ModelDosen>>( future: ListDosenProvider.getDosen(), builder: (context, snapshot) { if (snapshot.hasData) { return Expanded( child: ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { return Container( width: MediaQuery.of(context).size.width, decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all( Radius.circular(8), ), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), spreadRadius: 1, blurRadius: 9, offset: const Offset( 1, 2), // changes position of shadow ), ], ), child: Padding( padding: const EdgeInsets.all(14), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( data[index].name.toString(), style: bold6, ), Text( data[index].prodi.toString(), style: regular6, ), const SizedBox( height: 12, ), Row( children: [ SizedBox( width: 94, height: 32, child: TextButton( onPressed: () {}, style: TextButton.styleFrom( backgroundColor: const Color(0xffB3FFAE), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text( "Email", style: boldButton1.copyWith( color: const Color( 0xff379237, ), ), ), ), ), const SizedBox( width: 8, ), SizedBox( width: 94, height: 32, child: TextButton( onPressed: (() {}), style: TextButton.styleFrom( backgroundColor: const Color(0xffC5D5FF), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text( "Detail", style: boldButton2.copyWith( color: primaryColor, ), ), ), ), ], ) ], ), Image.asset( 'assets/images/user.png', width: 50, ) ], ), ), ); }, ), ); } else { return CircularProgressIndicator( color: primaryColor, ); } }, ), ), ); } }
问题排查与修复方案
核心错误点
- 未使用FutureBuilder的快照数据:你在ListView中调用
data[index].name,但data列表始终是空的,没有从FutureBuilder的snapshot.data中赋值,应该直接使用快照里的返回数据。 - 布局结构冲突:
Expanded需要嵌套在Column/Row等弹性布局容器中,直接放在Center里会导致ListView无法获取可用空间,无法渲染内容。 - 潜在类型不匹配:从注释的
fetchData方法看,你之前可能期望ModelDosen包含data字段,但当前API解析逻辑是直接返回List<ModelDosen>,需确认ModelDosen结构是否和API返回数据匹配。
修改后的Widget核心代码
@override Widget build(BuildContext context) { return Scaffold( appBar: PreferredSize( preferredSize: const Size.fromHeight(kToolbarHeight), child: CustomAppbar( title: 'Dosen', ), ), // 移除外层Center,让FutureBuilder直接作为body子组件 body: FutureBuilder<List<ModelDosen>>( future: ListDosenProvider.getDosen(), builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( padding: EdgeInsets.all(16), itemCount: snapshot.data!.length, itemBuilder: (context, index) { // 直接从快照中获取当前项数据 final dosen = snapshot.data![index]; return Container( width: MediaQuery.of(context).size.width, decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all(Radius.circular(8)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), spreadRadius: 1, blurRadius: 9, offset: const Offset(1, 2), ), ], ), margin: EdgeInsets.only(bottom: 12), child: Padding( padding: const EdgeInsets.all(14), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( dosen.name.toString(), style: bold6, ), Text( dosen.prodi.toString(), style: regular6, ), const SizedBox(height: 12), Row( children: [ SizedBox( width: 94, height: 32, child: TextButton( onPressed: () {}, style: TextButton.styleFrom( backgroundColor: const Color(0xffB3FFAE), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text( "Email", style: boldButton1.copyWith( color: const Color(0xff379237), ), ), ), ), const SizedBox(width: 8), SizedBox( width: 94, height: 32, child: TextButton( onPressed: () {}, style: TextButton.styleFrom( backgroundColor: const Color(0xffC5D5FF), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text( "Detail", style: boldButton2.copyWith( color: primaryColor, ), ), ), ), ], ) ], ), Image.asset( 'assets/images/user.png', width: 50, ) ], ), ), ); }, ); } else if (snapshot.hasError) { // 增加错误状态提示 return Center(child: Text('加载失败: ${snapshot.error}')); } else { return Center( child: CircularProgressIndicator(color: primaryColor), ); } }, ), ); }
额外优化点
- 移除了多余的
Center和Expanded,让ListView自动占满可用空间 - 增加列表项间距,提升UI可读性
- 添加错误状态处理,方便排查加载失败问题
内容的提问来源于stack exchange,提问作者sharon
相关产品推荐
相关产品推荐

