ListView Builder处理API空结果时出现NoSuchMethodError问题求助
问题解决:Flutter ListView Builder无API数据时抛出NoSuchMethodError
问题描述
使用Flutter的ListView Builder展示API请求结果时,API返回数据时功能正常,但无数据返回时抛出NoSuchMethodError,错误信息:
no suchMethodError:"map" Dynamic call with incorrect number of type arguments Expected 2 actual 1 Receiver instance of 'jsonMap' Arguments:[instance of dynamic)=> historique]
相关代码:
import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:tentative_formulaire_konamicash/pages/post_history.dart'; import 'package:tentative_formulaire_konamicash/pages/test_vfetch.dart'; class gamehistory extends StatefulWidget { const gamehistory({ super.key, required this.email, required this.password, }); final String password; final String email; @override State<gamehistory> createState() => _gamehistoryState(); } class _gamehistoryState extends State<gamehistory> { Future<void> equipe(String lepgagnant) async { var url = Uri.parse('https://konamicash.com/jeux_app'); var response = await http.post(url, headers: { "Accept": "application/json", "Access-Control-Allow-Origin": "*" }, body: { "email": widget.email, }); if (response.statusCode == 200) { var retour = jsonDecode(response.body); print(retour); setState(() {}); } } Future<void> contenu() async { var url = Uri.parse('https://konamicash.com/vfetch_app'); var response = await http.post(url, headers: { "Accept": "application/json", "Access-Control-Allow-Origin": "*" }, body: { "email": widget.email, }); if (response.statusCode == 200) { var reponse = jsonDecode(response.body); if (reponse['situation'] == 0) { print('no data'); } else { Navigator.push( context, PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => TestVfetch(mail: widget.email, password: widget.password), transitionsBuilder: (context, animation, secondaryAnimation, child) { animation = CurvedAnimation(parent: animation, curve: Curves.ease); return FadeTransition( opacity: animation, child: child, ); }), ); } print(reponse); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('message'), ), ); } } late Future<List<history>> usersFuture = vfetchdata(); Future<List<history>> vfetchdata() async { final url = Uri.parse('https://konamicash.com/jeux_app'); final response = await http.post(url, headers: { "Accept": "application/json", "Access-Control-Allow-Origin": "*" }, body: { "email": widget.email, }); final body = json.decode(response.body); return body.map<history>(history.fromJson).toList(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('konami'), ), body: Center( child: FutureBuilder<List<history>>( future: usersFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } else if (snapshot.hasData) { final users = snapshot.data!; return buildstories(users); } else if (snapshot.hasError) { return Text('${snapshot.error}'); } else { return const Text('nothing to display'); } }), ), ); } } Widget buildstories(List<history> users) => ListView.builder( itemCount: users.length, itemBuilder: (context, index) { final user = users[index]; return Card( child: ListTile( leading: CircleAvatar( backgroundImage: NetworkImage('https://konamicash.com/${user.image_equipe}'), ), title: Text('${user.name} ${user.mail}'), subtitle: Text(user.phone), ), ); }); //My class history class history { final String name; final String mail; final String phone; final String cote; const history( {required this.name, required this.mail, required this.phone, }); static history fromJson(json) => history( nom: json['name'], prenoms: json['mail'], numero_de_telephone: json['phone'], ); }
错误原因
- API返回格式不一致:有数据时返回数组,无数据时返回JSON对象(如
{"situation":0}),此时调用body.map<history>(...)会报错,因为map是数组的方法,JSON对象没有这个方法。 - history类定义错误:
fromJson方法中使用的参数名(nom、prenoms、numero_de_telephone)与类构造函数的参数名(name、mail、phone)不匹配,会导致字段赋值失败。buildstories中使用了user.image_equipe,但history类中未定义该字段。
解决方案
1. 修复API数据处理逻辑
修改vfetchdata方法,判断返回的是数组还是对象,无数据时返回空列表:
Future<List<history>> vfetchdata() async { final url = Uri.parse('https://konamicash.com/jeux_app'); final response = await http.post(url, headers: { "Accept": "application/json", "Access-Control-Allow-Origin": "*" }, body: { "email": widget.email, }); final body = json.decode(response.body); // 判断是否为数组,不是则返回空列表 if (body is List) { return body.map<history>(history.fromJson).toList(); } else { // 无数据时返回空列表 return []; } }
2. 修正history类定义
补全缺失字段,修正fromJson参数匹配问题:
class history { final String name; final String mail; final String phone; final String cote; final String imageEquipe; // 添加缺失的image_equipe字段 const history({ required this.name, required this.mail, required this.phone, required this.cote, required this.imageEquipe, }); static history fromJson(Map<String, dynamic> json) => history( name: json['name'], mail: json['mail'], phone: json['phone'], cote: json['cote'], imageEquipe: json['image_equipe'], // 匹配API返回的字段名 ); }
3. 修复ListView中的字段引用
修改buildstories中的字段引用,使用正确的类字段名:
Widget buildstories(List<history> users) => ListView.builder( itemCount: users.length, itemBuilder: (context, index) { final user = users[index]; return Card( child: ListTile( leading: CircleAvatar( backgroundImage: NetworkImage('https://konamicash.com/${user.imageEquipe}'), // 使用修正后的字段名 ), title: Text('${user.name} ${user.mail}'), subtitle: Text(user.phone), ), ); });
4. 优化FutureBuilder空数据显示
在FutureBuilder中判断列表是否为空,显示友好提示:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('konami'), ), body: Center( child: FutureBuilder<List<history>>( future: usersFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } else if (snapshot.hasData) { final users = snapshot.data!; // 列表为空时显示提示 if (users.isEmpty) { return const Text('暂无历史记录'); } return buildstories(users); } else if (snapshot.hasError) { return Text('加载失败:${snapshot.error}'); } else { return const Text('暂无数据'); } }), ), ); }
内容的提问来源于stack exchange,提问作者Deenan Djigbenou
相关产品推荐
相关产品推荐

