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

Flutter中NoSuchMethodError求助:Map数据加载到UI失败

Flutter加载Map数据到UI时的NoSuchMethodError问题解决

遇到的错误

  • NoSuchMethodError (NoSuchMethodError: Class 'Symbol' has no instance method '[]'. Receiver: Map<dynamic, dynamic> Tried calling: )
  • NoSuchMethodError (NoSuchMethodError: Class 'Type' has no instance method '[]'. Receiver: Map<dynamic, dynamic> Tried calling: [])

项目原代码

import 'dart:async';
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class Signal {
  final String sg_symbol;
  final String sg_timeframe;
  final String sg_exchange;
  final String sg_unitDatetime;
  final int sg_signal;
  final String sg_algorithm;

  Signal({
    required this.sg_symbol,
    required this.sg_timeframe,
    required this.sg_exchange,
    required this.sg_unitDatetime,
    required this.sg_signal,
    required this.sg_algorithm,
  });

  factory Signal.fromJson(Map<String, dynamic> json) {
    return Signal(
      sg_symbol: json['symbol'],
      sg_timeframe: json['timeframe'],
      sg_exchange: json['exchange'],
      sg_unitDatetime: json['unit_datetime'],
      sg_signal: json['signal'],
      sg_algorithm: json['algorithm'],
    );
  }
}

Future<List<Signal>> fetchSignal() async {
  final response = await http.get(Uri.parse('https://neutiad2.gabia.io/signal'));
  if (response.statusCode == 200) {
    // 만약 서버로의 요청이 성공하면, JSON을 파싱합니다.
    print(json.decode(response.body));
    List<dynamic> body = json.decode(response.body);
    List<Signal> allSignal =
        body.map((dynamic item) => Signal.fromJson(item)).toList();
    return allSignal;
  } else {
    // 만약 요청이 실패하면, 에러를 던집니다.
    throw Exception('Failed to load Signal');
  }
}

class TestPage extends StatefulWidget {
  const TestPage({Key? key}) : super(key: key);

  @override
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  Future<List<Signal>>? signal;

  @override
  void initState() {
    super.initState();
    signal = fetchSignal();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('info', style: TextStyle(color: Colors.white)),
          centerTitle: true,
        ),
        body: SingleChildScrollView(
          child: Center(
            child: Column(
              children: [
                FutureBuilder<List<Signal>>(
                  //통신데이터 가져오기
                  future: signal,
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      return buildList(snapshot.data!);
                    } else if (snapshot.hasError) {
                      return Text("${snapshot.error}에러!!");
                    }
                    return CircularProgressIndicator();
                  },
                ),
              ],
            ),
          ),
        ));
  }

  Widget buildList(snapshot) {
    return SizedBox(
      height: 150,
      child: ScrollConfiguration(
        behavior: MyCustomScrollBehavior(),
        child: ListView.builder(
            itemCount: snapshot.length,
            scrollDirection: Axis.horizontal,
            itemBuilder: (context, i) {
              return Container(
                decoration: BoxDecoration(color: Colors.red.shade100),
                margin: EdgeInsets.symmetric(horizontal: 1),
                height: 150,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Text('고객번호:' + snapshot[i].symbol.toString(),
                        style: TextStyle(fontSize: 20)),
                    Text('고객명:' + snapshot[i].timeframe.toString(),
                        style: TextStyle(fontSize: 20)),
                    Text('계좌 아이디:' + snapshot[i].exchange.toString(),
                        style: TextStyle(fontSize: 20)),
                    Text('잔액:' + snapshot[i].unitDatetime.toString(),
                        style: TextStyle(fontSize: 20)),
                    Text('잔액:' + snapshot[i].signal.toString(),
                        style: TextStyle(fontSize: 20)),
                    Text('잔액:' + snapshot[i].algorithm.toString(),
                        style: TextStyle(fontSize: 20)),
                  ],
                ),
              );
            }),
      ),
    );
  }
}

class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // Override behavior methods and getters like dragDevices
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
        // etc.
      };
}

问题原因

错误根源在于访问Signal对象属性时使用了错误的名称:

  • Signal类定义的属性是sg_symbol、sg_timeframe等带sg_前缀的名称,但在buildList方法中,错误地调用了snapshot[i].symbol、snapshot[i].timeframe等不存在的属性。
  • Dart中,调用不存在的实例属性时,会默认将其解析为Symbol类型的标识符,从而触发NoSuchMethodError错误。

解决方案

修改buildList方法中的属性调用,替换为Signal类中实际定义的属性名,并优化参数类型:

  1. 指定buildList的参数类型为List<Signal>,避免类型不确定的问题;
  2. 将所有snapshot[i].xxx替换为对应的sg_xxx属性。

修改后的buildList方法代码:

Widget buildList(List<Signal> snapshot) {
  return SizedBox(
    height: 150,
    child: ScrollConfiguration(
      behavior: MyCustomScrollBehavior(),
      child: ListView.builder(
          itemCount: snapshot.length,
          scrollDirection: Axis.horizontal,
          itemBuilder: (context, i) {
            return Container(
              decoration: BoxDecoration(color: Colors.red.shade100),
              margin: EdgeInsets.symmetric(horizontal: 1),
              height: 150,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Text('고객번호:' + snapshot[i].sg_symbol.toString(),
                      style: TextStyle(fontSize: 20)),
                  Text('고객명:' + snapshot[i].sg_timeframe.toString(),
                      style: TextStyle(fontSize: 20)),
                  Text('계좌 아이디:' + snapshot[i].sg_exchange.toString(),
                      style: TextStyle(fontSize: 20)),
                  Text('잔액:' + snapshot[i].sg_unitDatetime.toString(),
                      style: TextStyle(fontSize: 20)),
                  Text('잔액:' + snapshot[i].sg_signal.toString(),
                      style: TextStyle(fontSize: 20)),
                  Text('잔액:' + snapshot[i].sg_algorithm.toString(),
                      style: TextStyle(fontSize: 20)),
                ],
              ),
            );
          }),
    ),
  );
}

同时,在FutureBuilder的builder回调中,snapshot.data是可空类型,建议加上非空断言snapshot.data!(或做空判断),避免潜在的空指针问题。

内容的提问来源于stack exchange,提问作者이상현

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:16:01