Flutter如何展示Node.js返回的API数据并实现列表项点击跳转
问题根因
你代码中核心错误是JSON反序列化逻辑不符合数据结构:
- 服务端返回的
response.body本身就是合法的对象数组JSON字符串,你额外拼接[]会将数据转为嵌套数组[[{...},{...}]],遍历的时候只会拿到外层数组的第一个元素(也就是完整的科目数组),所以只能展示第一条数据 - 没有调用
jsonDecode对JSON字符串做反序列化,直接强制类型转换会触发类型不匹配报错
解决方案
1. 修正fetchSubject请求方法
import 'dart:convert'; Future<List<Subject>> fetchSubject() async { var prefs = await SharedPreferences.getInstance(); var token = prefs.getString('token'); final response = await http.get( Uri.parse('http://localhost:8000/subjects'), headers: {'x-access-token': token!}); // 先判断请求成功再解析 if (response.statusCode == 200) { // 直接反序列化响应字符串,不需要额外拼接[] List<dynamic> list = jsonDecode(response.body); List<Subject> subjectList = list.map((item) => Subject.fromJson(item)).toList(); return subjectList; } else { throw Exception('请求科目数据失败'); } }
2. 修正Subject模型类
将parseJson改为静态方法方便调用,删除冗余逻辑:
import 'dart:convert'; class Subject { final String name; Subject({ required this.name, }); factory Subject.fromJson(Map<String, dynamic> json) { return Subject(name: json['NAME'] as String); } // 改为静态方法,外部可直接调用 static List<Subject> parseJson(String responseBody) { final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>(); return parsed.map<Subject>((json) => Subject.fromJson(json)).toList(); } }
3. 界面列表展示+点击跳转实现
在你的State类中按以下逻辑编写FutureBuilder:
late Future<List<Subject>> futureSubject; @override void initState() { super.initState(); futureSubject = fetchSubject(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('科目列表')), body: FutureBuilder<List<Subject>>( future: futureSubject, builder: (context, snapshot) { if (snapshot.hasData) { // 用ListView展示所有科目 return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { Subject subject = snapshot.data![index]; return ListTile( title: Text(subject.name), // 点击跳转逻辑,替换为你对应的目标页面 onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => YourTargetPage(subject: subject), ), ); }, ); }, ); } else if (snapshot.hasError) { return Center(child: Text('加载失败: ${snapshot.error}')); } return const Center(child: CircularProgressIndicator()); }, ), ); }
你只需要将上述代码中的YourTargetPage替换为你实际要跳转的页面组件,即可实现点击科目跳转到对应页面的需求。
内容的提问来源于stack exchange,提问作者Irwin
相关产品推荐
相关产品推荐

