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类中实际定义的属性名,并优化参数类型:
- 指定
buildList的参数类型为List<Signal>,避免类型不确定的问题; - 将所有
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,提问作者이상현
相关产品推荐
相关产品推荐

