学习从JSONPlaceholder获取数据时遇错误,求技术协助
JSONPlaceholder异步请求数据错误排查
问题描述
我在学习从JSONPlaceholder获取异步请求数据的过程中遇到了错误,以下是相关的Web入口HTML代码及Flutter Dart实现代码,请帮忙排查问题:
Web入口HTML代码
<!-- If you are serving your web app in a path other than the root, change the href value below to reflect the base path you are serving from. The path provided below has to start and end with a slash "/" in order for it to work correctly. For more details: * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base This is a placeholder for base href that will be replaced by the value of the `--base-href` argument provided to `flutter build`. --> <base href="/"> <meta charset="UTF-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="description" content="A new Flutter project."> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-title" content="flutter_application_1"> <link rel="apple-touch-icon" href="icons/Icon-192.png"> <link rel="icon" type="image/png" href="favicon.png"/> flutter_application_1 <link rel="manifest" href="manifest.json"> // The value below is injected by flutter build, do not touch. var serviceWorkerVersion = null; <script src="flutter.js" defer> window.addEventListener('load', function(ev) { // Download main.dart.js _flutter.loader.loadEntrypoint({ serviceWorker: { serviceWorkerVersion: serviceWorkerVersion, } }).then(function(engineInitializer) { return engineInitializer.initializeEngine(); }).then(function(appRunner) { return appRunner.runApp(); }); }); </script>
Flutter Dart实现代码
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; class JasonParsingSimple extends StatefulWidget { const JasonParsingSimple({super.key}); @override State<JasonParsingSimple> createState() => _JasonParsingSimpleState(); } class _JasonParsingSimpleState extends State<JasonParsingSimple> { @override void initState() { Future data; // TODO: implement initState super.initState(); data = getData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Parsing Jason"), ), // body: Center( // child: Container( // child: FutureBuilder( // future: getData(), // builder: (context, AsyncSnapshot<dynamic> snapshot) { // return Text(snapshot.data[0]['title']); // }), // )), ); } Future getData() async { var data; String url = "https://jsonplaceholder.typicode.com/posts"; Network network = Network(url); data = network.fetchData(); // data.then((value) { // print(value[3]); // }); return data; } } class Network { final String url; Network(this.url); Future fetchData() async { print("$url"); Response response = await get(Uri.parse("url")); if (response.statusCode == 200) { print(json.encode(response.body)); return json.encode(response.body); } else { print(response.statusCode); } } }
错误排查与修复方案
1. 请求URL参数错误
Network类的fetchData方法中,传入Uri.parse("url")是把字符串"url"作为请求地址,而非类成员变量url,导致请求发送到无效地址。
修复:
Response response = await get(Uri.parse(url)); // 移除引号,使用类成员变量
2. JSON解析方向错误
当前用json.encode(response.body)将响应字符串再次编码为JSON字符串,实际需要将响应的JSON字符串解码为Dart对象(列表/Map),应使用json.decode。
修复:
if (response.statusCode == 200) { final decodedData = json.decode(response.body); print(decodedData); return decodedData; }
3. FutureBuilder优化(注释代码启用建议)
如果要启用注释中的FutureBuilder,需注意:
- 不要在
build方法中直接调用getData(),否则每次组件重建都会发起新请求,应在initState中初始化并保存Future对象 - 必须处理
snapshot的不同状态(加载中、错误、空数据、成功),避免空指针异常
优化后的State类:
class _JasonParsingSimpleState extends State<JasonParsingSimple> { late Future<List<dynamic>> data; @override void initState() { super.initState(); data = getData(); // 仅初始化一次 } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("解析JSON"), ), body: Center( child: FutureBuilder<List<dynamic>>( future: data, builder: (context, AsyncSnapshot<List<dynamic>> snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(); // 加载中显示转圈 } else if (snapshot.hasError) { return Text("请求出错: ${snapshot.error}"); // 错误提示 } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return Text("无数据"); // 空数据提示 } else { return Text(snapshot.data![0]['title']); // 成功展示第一条数据的标题 } }, ), ), ); } // getData方法保持修复后状态 }
4. 命名规范修正
类名JasonParsingSimple应为JsonParsingSimple(正确拼写JSON),虽不影响功能,但遵循规范更易维护。
修复后的完整Network类
class Network { final String url; Network(this.url); Future<List<dynamic>> fetchData() async { print("$url"); Response response = await get(Uri.parse(url)); if (response.statusCode == 200) { final decodedData = json.decode(response.body); print(decodedData); return decodedData; } else { print(response.statusCode); throw Exception("请求失败,状态码: ${response.statusCode}"); // 抛出异常供FutureBuilder捕获 } } }
内容的提问来源于stack exchange,提问作者Ashwani Verma
相关产品推荐
相关产品推荐

