我收到此帖子标题中的错误消息,我无法解读为正确访问我从网站请求的数据而需要做的事情。代码如下:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
Future<SearchNews> fetchNews() async {
String key = 'xxx';
final response =
await http.get('https://newsapi.org/v2/everything?q=bitcoin&apiKey=$key');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return SearchNews.fromJson(json.decode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load news');
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<SearchNews> futureNews;
@override
void initState() {
// TODO: implement initState
super.initState();
futureNews = fetchNews();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FutureBuilder<SearchNews>(
future: futureNews,
builder: (context,snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.articles[0].title);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
}
),
],
),
),
);
}
}
class Source
{
String id;
String name;
Source({this.id, this.name});
factory Source.fromJson(Map<String, dynamic> json){
return Source(
id: json['id'],
name: json['name'],
);
}
}
class Article
{
Source source;
String author;
String title;
String description;
String url;
String urlToImage;
String publishedAt;
String content;
Article({this.source, this.author,this.title,this.description,this.url,this.urlToImage,this.publishedAt,this.content});
factory Article.fromJson(Map<String, dynamic> json){
return Article(
source: json['source'],
author: json['author'],
title: json['title'],
description: json['description'],
url: json['url'],
urlToImage: json['urlToImage'],
publishedAt: json['publishedAt'],
content: json['content'],
);
}
}
class SearchNews
{
String status;
int totalResults;
List<Article> articles;
SearchNews({this.status,this.totalResults,this.articles});
factory SearchNews.fromJson(Map<String,dynamic>json){
return SearchNews(
status: json['status'],
totalResults: json['totalResults'],
articles: json['articles'].cast<Article>(),
);
}
}
发生错误的控制台会产生以下内容:
I/flutter ( 6644): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 6644): The following _CastError was thrown building FutureBuilder<SearchNews>(dirty, state:
I/flutter ( 6644): _FutureBuilderState<SearchNews>#43653):
I/flutter ( 6644): type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Article' in type cast
I/flutter ( 6644):
I/flutter ( 6644): The relevant error-causing widget was:
I/flutter ( 6644): FutureBuilder<SearchNews>
I/flutter ( 6644): file:///xxx/main.dart:73:12
I/flutter ( 6644):
I/flutter ( 6644): When the exception was thrown, this was the stack:
I/flutter ( 6644): #0 _CastListBase.[] (dart:_internal/cast.dart:101:46)
I/flutter ( 6644): #1 _MyHomePageState.build.<anonymous closure> (package:news_receiver_test/main.dart:77:52)
I/flutter ( 6644): #2 _FutureBuilderState.build (package:flutter/src/widgets/async.dart)
I/flutter ( 6644): #3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4334:27)
I/flutter ( 6644): #4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4223:15)
I/flutter ( 6644): #5 Element.rebuild (package:flutter/src/widgets/framework.dart:3947:5)
I/flutter ( 6644): #6 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2432:33)
I/flutter ( 6644): #7 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:773:20)
I/flutter ( 6644): #8 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:283:5)
I/flutter ( 6644): #9 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1102:15)
I/flutter ( 6644): #10 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1041:9)
I/flutter ( 6644): #11 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:957:5)
I/flutter ( 6644): #15 _invoke (dart:ui/hooks.dart:259:10)
I/flutter ( 6644): #16 _drawFrame (dart:ui/hooks.dart:217:3)
I/flutter ( 6644): (elided 3 frames from package dart:async)
I/flutter ( 6644):
I/flutter ( 6644): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter ( 6644): Another exception was thrown: A RenderFlex overflowed by 99306 pixels on the bottom.
Lost connection to device.
在此之前,我遇到了错误:类型'List不是类型'List'的子类型,然后我通过在末尾添加.cast<Article>()
来消除了该错误。该行的:
articles: json['articles'].cast<Article>(),
答案 0 :(得分:0)
我想您在从远程服务返回的json中有一个文章数组。
您必须解析文章数组。
尝试类似这样的方法。在SearchNews
类中
factory SearchNews.fromJson(Map<String,dynamic>json){
var auxList = json['articles'] as List;
List<Article> listArticle = auxList.map((i) =>
Article.fromJson(i)).toList();
return SearchNews(
status: json['status'],
totalResults: json['totalResults'],
articles: listArticle,
);
}
答案 1 :(得分:0)
在此示例中,您尝试将复杂的动态类型强制转换为复杂的对象。 而且这些类型与执行直接投射时不兼容。
cast
的{{1}}方法似乎是非常实验性的。请参考以下堆栈溢出答案:In Dart, syntactically nice way to cast dynamic to given type or return null?
在您的示例中。 dynamic
对象由类型为Article
的另一个复杂对象组成。在此示例中,您直接尝试将Source
对象转换为dynamic
对象:
Source
相反,应该使用已经编写的return Article(
source: json['source'],
author: json['author'],
title: json['title'],
description: json['description'],
url: json['url'],
urlToImage: json['urlToImage'],
publishedAt: json['publishedAt'],
content: json['content'],
);
方法:
Source.fromJson
类似地,您可以利用return Article(
source: Source.fromJson(json['source']),
author: json['author'],
title: json['title'],
description: json['description'],
url: json['url'],
urlToImage: json['urlToImage'],
publishedAt: json['publishedAt'],
content: json['content'],
);
中fromJson
的{{1}}方法。
Article
在这里,我们正在使用SearchNews
表达式和您的factory SearchNews.fromJson(Map<String,dynamic>json){
return SearchNews(
status: json['status'],
totalResults: json['totalResults'],
articles: List<Article>.from(json["articles"].map((x) => Article.fromJson(x))),
);
}
工厂方法将动态列表对象中的每个元素转换为文章,以创建类型为map
的列表。
希望这会有所帮助。