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

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'],
);
}

错误原因

  1. API返回格式不一致:有数据时返回数组,无数据时返回JSON对象(如{"situation":0}),此时调用body.map<history>(...)会报错,因为map是数组的方法,JSON对象没有这个方法。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:24:48