【问题标题】:type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of 'Article' in type casttype '_InternalLinkedHashMap<String, dynamic>' 不是类型转换中 'Article' 的子类型
【发布时间】:2020-07-21 01:19:04
【问题描述】:

我收到了这篇文章标题中的错误消息,我无法理解我需要做什么才能正确访问我从网站请求的数据。代码如下:

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.

在此之前,我遇到过错误:type 'List is not a subtype of type 'List' 然后我通过在末尾添加.cast&lt;Article&gt;() 摆脱了线: articles: json['articles'].cast&lt;Article&gt;(),

【问题讨论】:

    标签: json android-studio flutter dart dynamic


    【解决方案1】:

    我猜你在远程服务返回的 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,
      );
    }
    

    【讨论】:

    • 感谢您的贡献,使用您提供的修改并结合`source: Source.fromJson(json['source']),`来自用户 1ujn4s 的贡献,解决方案似乎有效。
    【解决方案2】:

    在此示例中,您尝试将复杂的动态类型转换为复杂的对象。 而且这些类型不兼容,无法直接转换。

    dynamiccast 方法似乎是非常实验性的。请参考这个堆栈溢出答案:In Dart, syntactically nice way to cast dynamic to given type or return null?

    在你的例子中。一个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'],
        );
    

    同样,您可以在SearchNews 中使用ArticlefromJson 方法。

    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 表达式和您的Article.fromJson 工厂方法将动态列表对象中的每个元素转换为文章,以创建List&lt;Article&gt; 类型的列表。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的贡献,使用您提供的修正并结合讨论从用户 encubos 解析单个文章的贡献,该解决方案似乎有效。
    猜你喜欢
    • 1970-01-01
    • 2019-01-26
    • 2021-06-19
    • 2019-05-02
    • 2020-03-04
    • 2021-01-22
    • 2019-08-28
    • 1970-01-01
    • 2021-04-03
    相关资源
    最近更新 更多