类型'_InternalLinkedHashMap <String,dynamic>'不是类型转换

时间:2020-04-08 15:07:08

标签: json android-studio flutter dart dynamic

我收到此帖子标题中的错误消息,我无法解读为正确访问我从网站请求的数据而需要做的事情。代码如下:

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>(),

2 个答案:

答案 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的列表。

希望这会有所帮助。