如何在颤振中解析json?
Posted
技术标签:
【中文标题】如何在颤振中解析json?【英文标题】:How to parse json in flutter? 【发布时间】:2020-03-01 12:22:30 【问题描述】:我想创建一个新闻应用,我使用 newsapi.org 作为来源。
我正在尝试获取来自 Http 库的 JSON 数据。
我在下面提供了完整的代码。
它没有给我任何错误,但没有加载数据,当我打印数据时,它打印一切正常,但我无法显示它。
我不知道是什么问题,但我所有的项目都停止了这个问题。
我正在为此代码寻找解决方案,因为它不起作用。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:newly/services/networking.dart';
import 'package:newly/widgets/article.dart';
class NewsScreen extends StatefulWidget
@override
_NewsScreenState createState() => _NewsScreenState();
class _NewsScreenState extends State<NewsScreen>
List<Article> articles = [];
NetworkHelper networkHelper = NetworkHelper(
url:
'https://newsapi.org/v2/everything?q=bitcoin&apiKey=392495172bab4b3885ae93760df54b91',
);
Future<List<Widget>> getNews() async
var newsData = await networkHelper.getData();
for (int i = 0; i < await newsData['articles'].length; i++)
var title = await newsData['articles'][i]['title'];
var urlToImage = await newsData['articles'][i]['urlToImage'];
var content = await newsData['articles'][i]['content'];
var author = await newsData['articles'][i]['author'];
var url = await newsData['articles'][i]['url'];
print(title);
print(urlToImage);
print(url);
print(content);
print(author);
print('123456789123456789123456789123456789');
articles.add(
Article(
author: author,
content: content,
title: title,
url: url,
urlToImage: urlToImage,
),
);
print(articles[0].author);
return articles;
Future<List<Article>> showArticles() async
var data = await get(
'https://newsapi.org/v2/everything?q=bitcoin&apiKey=392495172bab4b3885ae93760df54b91',
);
var dataDecoded = await json.decode(data.body);
List<Article> articles = [];
await dataDecoded.forEach(
(article)
articles.add(
Article(
author: article['author'],
content: article['content'],
title: article['title'],
url: article['url'],
urlToImage: article['urlToImage'],
),
);
,
);
return articles;
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
centerTitle: true,
title: Text(
'Newly',
style: TextStyle(
color: Colors.white,
),
),
),
body: FutureBuilder(
future: getNews(),
builder: (context, snapshot)
return ListView(
children: articles,
);
,
),
);
网络助手:
import 'package:http/http.dart' as http;
import 'dart:convert';
class NetworkHelper
NetworkHelper(this.url);
final String url;
Future getData() async
http.Response response = await http.get(url);
if (response.statusCode == 200)
String data = response.body;
return json.decode(data);
else
print('something wrong');
print(response.statusCode);
【问题讨论】:
能否请您出示您的NetworkHelper
班级?
我已经更新了
好的,我会回答的
【参考方案1】:
在处理 json 数据时
最好的做法是为此创建一个模型,然后通过 api 获取数据
创建一个模型和一个类很容易,不费力,让你的工作很容易;)
用于为您的项目创建模型
访问https://javiercbk.github.io/json_to_dart/
只需copy your json data
和paste in the textField
,您只需单击一下即可准备好模型类
用于访问数据
Test _test = Test.fromJson(response.body);
就是这样。
参考下图
【讨论】:
转换响应模型的简单方法。 但仍然没有从响应中获取数据相同的错误 - 方法 '[]' 在 null 上调用。 E/颤振(8569):接收者:空 @s.j 该错误反映了从 api 端您没有获得任何数据,或者您可能没有正确访问它。尝试先检查响应【参考方案2】:您也可以使用 FutureBuilder
来完成此操作,如果您愿意,@Mustafa 答案将起作用。
Future<List<Article>> showArticles() async
var data = await networkHelper.getData();
List<Article> articlesArr = [];
await data['articles'].forEach(
(article)
articlesArr.add(
Article(
author: article['author'],
content: article['content'],
title: article['title'],
url: article['url'],
urlToImage: article['urlToImage'],
),
);
,
);
return articlesArr;
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
centerTitle: true,
title: Text(
'Newly',
style: TextStyle(
color: Colors.white,
),
),
),
body: FutureBuilder<List<Article>>(
future: showArticles(),
builder: (context, snapshot)
if (snapshot.hasData)
return ListView(
children: snapshot.data.map((article)
return Container(
padding: EdgeInsets.all(8.0),
child: Text(article.author),
);
).toList(),
);
else
return Container(
color: Colors.blue,
);
,
),
);
【讨论】:
【参考方案3】:问题在于显示文章。而且正如@ISpam Ossama 所说,你必须使用 setState 将数据添加到这样的列表中。
void getNews() async
var newsData = await networkHelper.getData();
for (int i = 0; i < newsData['articles'].length; i++)
var title = newsData['articles'][i]['title'];
var urlToImage = newsData['articles'][i]['urlToImage'];
var content = newsData['articles'][i]['content'];
var author = newsData['articles'][i]['author'];
var url = newsData['articles'][i]['url'];
print(title);
print(urlToImage);
print(url);
print(content);
print(author);
print('123456789123456789123456789123456789');
setState(()
articles.add(
Article(
author: author,
content: content,
title: title,
url: url,
urlToImage: urlToImage,
),
);
);
print(articles[0].author);
现在,你必须像这样显示文章。
ListView.builder(
itemCount: articles.length,
itemBuilder: (BuildContext ctxt, int index)
return Text(articles[index].title);
,
)
希望对你有帮助!
【讨论】:
为什么在所有语句中都使用 await ?喜欢,await newsData['articles'][i]['title'];
并且还在setstate中发出。因为如果我们得到 1000 个数据,那么 Widget 将重建 1000 次。它应该在 for 循环之外。
是的你是对的,我真的很抱歉,我没有注意到,我会更新答案
我了解 await 问题,但是 setState 的替代解决方案是什么?
先在本地数组中添加所有数据,然后在for循环之后用全局设置状态。【参考方案4】:
在将文章添加到数组之前尝试 setState
【讨论】:
以上是关于如何在颤振中解析json?的主要内容,如果未能解决你的问题,请参考以下文章