Flutter JSON解析报错及点击浮动按钮带加载动画刷新功能实现问题
问题解决方案
错误根因
- JSON解析报错是因为返回结果是数组类型,原有代码直接将数组转为单个Map对象传入Album.fromJson导致类型不匹配,同时Album.fromJson中取了不存在的
name字段,实际返回字段为title - 点击刷新不显示加载圈的问题,原有逻辑是对的,只要修正数据类型后,setState更新future变量即可触发FutureBuilder重新进入加载状态
修正后完整空安全代码
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; // 替换为你的实际接口地址 const String myLocksEp = 'https://xxx.com/xxx'; Future<List<Album>> fetchAlbum() async { print("Fetching json...."); final response = await http.get( Uri.parse(myLocksEp), ); if (response.statusCode == 200) { print(response.body); // 解析数组:先转成List<dynamic>,再逐个转为Album对象 List<dynamic> jsonList = jsonDecode(response.body); return jsonList.map((jsonItem) => Album.fromJson(jsonItem)).toList(); } else { throw Exception('Failed to load album'); } } class Album { final int id; final String title; final int userId; Album({required this.id, required this.title, required this.userId}); factory Album.fromJson(Map<String, dynamic> json) { return Album( id: json['id'], title: json['title'], // 修正字段取值,和返回JSON对齐 userId: json['userId'], ); } } void main() { runApp(const MyLocks()); } // Dart类名规范使用大驼峰 class MyLocks extends StatefulWidget { const MyLocks({super.key}); @override _MyAppState createState() { return _MyAppState(); } } class _MyAppState extends State<MyLocks> { // 调整为List<Album>类型 late Future<List<Album>> _futureAlbum; @override void initState() { super.initState(); _futureAlbum = fetchAlbum(); } @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( body: Container( alignment: Alignment.center, padding: const EdgeInsets.all(8.0), // 调整FutureBuilder泛型为List<Album> child: FutureBuilder<List<Album>>( future: _futureAlbum, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.hasData) { // 加载完成返回ListView渲染列表 return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { Album item = snapshot.data![index]; return ListTile( title: Text(item.title), subtitle: Text("用户ID:${item.userId},ID:${item.id}"), ); }, ); } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } } // 加载中自动显示进度圈 return const CircularProgressIndicator(); }, ), ), floatingActionButton: FloatingActionButton( child: const Icon(Icons.refresh_outlined, color: Colors.black), backgroundColor: Colors.grey[200], onPressed: () { setState(() { _futureAlbum = fetchAlbum(); }); }, ), ), ); } }
核心修改说明
- 调整数据请求返回类型为
Future<List<Album>>,匹配接口返回的JSON数组结构,解析时遍历数组完成对象转换 - 修正Album.fromJson的字段取值错误,避免空值异常
- 加载完成后渲染ListView组件,将接口返回的所有数据展示为列表项
- 点击刷新按钮调用setState更新_futureAlbum变量,FutureBuilder检测到future变更后自动进入加载状态,展示CircularProgressIndicator,无需额外处理加载逻辑
内容的提问来源于stack exchange,提问作者Robbal
相关产品推荐
相关产品推荐

