如何从API获取数组数据并映射到Dart对象?代码修复指导
修复方案
1. 修正JSON数据格式(后端返回需保证合法)
你的示例JSON存在语法错误,每个键值对末尾需加逗号,字符串值要包裹引号:
[ { "channelId": 1, "channelTitle": "Photos", "channelImage": "pr01.jpg", "channelLastPost": null, "lastUpdate": null, "userRef": 1 }, { "channelId": 2, "channelTitle": "Science", "channelImage": "pr02.jpg", "channelLastPost": "For test ....", "lastUpdate": "2023-01-03", "userRef": 1 } ]
2. 修复ChannelListModel.dart
- 修正类型不匹配问题:
userRef是数字类型,需转为String;lastPost、lastUpdate可能为null,需设为可空类型 - 处理null值避免转换错误
class ChannelListModel { String creator; String? image; String title; String? lastPost; String? lastUpdate; ChannelListModel({ required this.creator, this.image, required this.title, this.lastPost, this.lastUpdate, }); factory ChannelListModel.fromJson(Map<String, dynamic> json) { return ChannelListModel( creator: json['userRef'].toString(), image: json['channelImage'], title: json['channelTitle'], lastPost: json['channelLastPost'], lastUpdate: json['lastUpdate'], ); } Map<String, dynamic> toJson() { return { "userRef": int.tryParse(creator), "channelImage": image, "channelTitle": title, "channelLastPost": lastPost, "lastUpdate": lastUpdate }; } }
3. 修复HttpRequest.dart
List<ChannelListModel>.fromJson是错误用法,List类没有该方法,需遍历JSON数组逐个转换为Model对象:
import 'dart:convert'; import 'package:http/http.dart' as http; import 'ChannelListModel.dart'; import 'base.dart'; class HttpServices { Future<List<ChannelListModel>> getChannelList() async { var url = base.BaseURL.channelListUrl; final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { List<dynamic> jsonList = jsonDecode(response.body); return jsonList.map((json) => ChannelListModel.fromJson(json)).toList(); } else { throw Exception('Failed to load channel list'); } } }
4. 修复ChannelPage.dart
initState不能直接赋值异步方法结果,需用setState更新状态- 添加加载状态和错误处理,提升用户体验
import 'package:flutter/material.dart'; import 'HttpServices.dart'; import 'ChannelListModel.dart'; import 'ChannelCard.dart'; class Channels extends StatefulWidget { const Channels({super.key}); @override State<Channels> createState() => _ChannelsState(); } class _ChannelsState extends State<Channels> { List<ChannelListModel> channels = []; bool isLoading = true; @override void initState() { super.initState(); getChannelsFromHttp(); } Future<void> getChannelsFromHttp() async { try { var httpService = HttpServices(); var result = await httpService.getChannelList(); setState(() { channels = result; isLoading = false; }); } catch (e) { setState(() { isLoading = false; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('加载失败:$e')), ); } } @override Widget build(BuildContext context) { return Scaffold( body: isLoading ? const Center(child: CircularProgressIndicator()) : channels.isEmpty ? const Center(child: Text('暂无频道数据')) : ListView.builder( itemCount: channels.length, itemBuilder: (context, index) => ChannelCard(channelModel: channels[index]), ), ); } }
代码拆分说明
保持现有文件拆分逻辑即可:
ChannelListModel.dart:仅存放数据模型类HttpRequest.dart:仅封装网络请求逻辑ChannelPage.dart:负责页面UI渲染与状态管理ChannelCard.dart:单独实现列表项Widget(需确保该文件存在)
内容的提问来源于stack exchange,提问作者Alex Wright
相关产品推荐
相关产品推荐

