【问题标题】:I am trying to fetch data from newsapi.org but having issue我正在尝试从 newsapi.org 获取数据但遇到问题
【发布时间】:2020-11-09 06:38:37
【问题描述】:

这是我的代码

错误:NoSuchMethodError:类 'Future' 没有实例 getter 'length'

void main() => runApp(MyApp());


class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key : key ) ;

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String urlToImage;
  // Future<Article> newslist;
  var newslist;

  @override
  void initState() {
    super.initState();
    newslist = fetchArticle();
  }

  @override
  Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Api calls',
          home: Scaffold(
            appBar: AppBar(title: Text('Api Calls'),),
            body: ListView.builder(
              shrinkWrap: true,
              itemCount: newslist.length,
          itemBuilder: (context, index) {
            return Image.network(newslist[index]['urlToImage']);
          })
      ),
      
    );
  }
}
class Article {
  final String author;
  final String title;
  final String description;
  final String publishedAt;
  final String urlToImage;
  final String url;

  Article({this.author, this.description, this.title, this.publishedAt, this.urlToImage, this.url});


  factory Article.fromJson(Map<String, dynamic> json) {
    return Article(
      author : json['author'],
      title: json['title'],
      description: json['description'],
      publishedAt: json['publishedAt'],
      url: json['url'],
      urlToImage: json['urlToImage']
    );
  
    
  }
  
}

  Future<Article> fetchArticle() async {

  var url = 
  'http://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=2e8e3846c42a4f64a6b1d98370bdeeea';
  
  final response = await http.get(url);

  if (response.statusCode == 200) {
    return Article.fromJson(json.decode(response.body));
  } else {
    throw Exception('Failed to load Article');
  }

}

lutter:在构建 MyApp(dirty, state: _MyAppState#c93f4) 时引发了以下 NoSuchMethodError: 颤振:“未来”类没有实例获取器“长度”。 颤振:接收者:“未来”的实例 颤振:尝试调用:长度 扑: 颤振:相关的导致错误的小部件是:

flutter:抛出异常时,堆栈如下: 颤振:#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5) 颤振:#1 _MyAppState.build(包:api/main.dart:35:35) 颤振:#2 StatefulElement.build(包:flutter/src/widgets/framework.dart:4619:28) 颤振:#3 ComponentElement.performRebuild(包:flutter/src/widgets/framework.dart:4502:15) 颤振:#4 StatefulElement.performRebuild(包:flutter/src/widgets/framework.dart:4675:11) 颤振:#5 Element.rebuild(包:颤振/src/widgets/framework.dart:4218:5) 颤振:#6 ComponentElement._firstBuild(包:flutter/src/widgets/framework.dart:4481:5) 颤振:#7 StatefulElement._firstBuild(包:flutter/src/widgets/framework.dart:4666:11) 颤振:#8 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4476:5) 颤振:#9 Element.inflateWidget(包:flutter/src/widgets/framework.dart:3446:14) 颤振:#10 Element.updateChild(包:颤振/src/widgets/framework.dart:3214:18) 颤振:#11 RenderObjectToWidgetElement._rebuild(包:flutter/src/widgets/binding.dart:1148:16) 颤振:#12 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1119:5) 颤振:#13 RenderObjectToWidgetAdapter.attachToRenderTree。 (包:flutter/src/widgets/binding.dart:1061:17) 颤振:#14 BuildOwner.buildScope(包:flutter/src/widgets/framework.dart:2607:19) 颤振:#15 RenderObjectToWidgetAdapter.attachToRenderTree(包:flutter/src/widgets/binding.dart:1060:13) 颤振:#16 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:941:7) 颤振:#17 WidgetsBinding.scheduleAttachRootWidget。 (包:flutter/src/widgets/binding.dart:922:7) 颤振:(从 _RawReceivePortImpl 类、_Timer 类、dart:async 和 dart:async-patch 中删除了 11 帧) 扑: 颤抖:

【问题讨论】:

  • 当应用程序执行 build() 时,'newlist' 值尚未准备好。所以你尝试使用'FutureBuilder'。api.flutter.dev/flutter/widgets/FutureBuilder-class.html
  • 了解更多关于Futures here的信息。
  • @KuKu 我想获取数据并将其显示在列表视图构建器中我应该怎么做?
  • Future != SomeType,如果你想访问 SomeType 中的方法,你必须等待 Future 变成 SomeType,正如编译器在某处所说,这个 await 关键字丢失了跨度>
  • @Sudip 我添加了答案。请检查以下答案。

标签: api http flutter


【解决方案1】:

您可以在下面复制粘贴运行完整代码
第 1 步:您可以使用 bool _isLoading 来控制加载状态
第 2 步:fetchArticle() 返回 Future&lt;List&lt;Article&gt;&gt; 不是 Future&lt;Article&gt;
第三步:使用payloadFromJson(response.body),可以看到Payload的完整代码类定义
第 4 步:当数据准备好时,将 _isLoading 设置为 false

void getData() async {
    newslist = await fetchArticle();
    setState(() {
      _isLoading = false;
    });
  }

工作演示

完整代码

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));

String payloadToJson(Payload data) => json.encode(data.toJson());

class Payload {
  Payload({
    this.status,
    this.totalResults,
    this.articles,
  });

  String status;
  int totalResults;
  List<Article> articles;

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        status: json["status"],
        totalResults: json["totalResults"],
        articles: List<Article>.from(
            json["articles"].map((x) => Article.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "status": status,
        "totalResults": totalResults,
        "articles": List<dynamic>.from(articles.map((x) => x.toJson())),
      };
}

class Article {
  Article({
    this.source,
    this.author,
    this.title,
    this.description,
    this.url,
    this.urlToImage,
    this.publishedAt,
    this.content,
  });

  Source source;
  String author;
  String title;
  String description;
  String url;
  String urlToImage;
  DateTime publishedAt;
  String content;

  factory Article.fromJson(Map<String, dynamic> json) => Article(
        source: Source.fromJson(json["source"]),
        author: json["author"],
        title: json["title"],
        description: json["description"],
        url: json["url"],
        urlToImage: json["urlToImage"],
        publishedAt: DateTime.parse(json["publishedAt"]),
        content: json["content"] == null ? null : json["content"],
      );

  Map<String, dynamic> toJson() => {
        "source": source.toJson(),
        "author": author,
        "title": title,
        "description": description,
        "url": url,
        "urlToImage": urlToImage,
        "publishedAt": publishedAt.toIso8601String(),
        "content": content == null ? null : content,
      };
}

class Source {
  Source({
    this.id,
    this.name,
  });

  String id;
  String name;

  factory Source.fromJson(Map<String, dynamic> json) => Source(
        id: json["id"] == null ? null : json["id"],
        name: json["name"],
      );

  Map<String, dynamic> toJson() => {
        "id": id == null ? null : id,
        "name": name,
      };
}

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String urlToImage;
  // Future<Article> newslist;
  List<Article> newslist;
  bool _isLoading = true;

  Future<List<Article>> fetchArticle() async {
    var url =
        'http://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=2e8e3846c42a4f64a6b1d98370bdeeea';

    final response = await http.get(url);

    if (response.statusCode == 200) {
      Payload payload = payloadFromJson(response.body);

      return payload.articles;
    } else {
      throw Exception('Failed to load Article');
    }
  }

  void getData() async {
    newslist = await fetchArticle();
    setState(() {
      _isLoading = false;
    });
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      getData();
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Api calls',
      home: Scaffold(
          appBar: AppBar(
            title: Text('Api Calls'),
          ),
          body: _isLoading
              ? Center(child: CircularProgressIndicator())
              : ListView.builder(
                  shrinkWrap: true,
                  itemCount: newslist.length,
                  itemBuilder: (context, index) {
                    return Image.network(newslist[index].urlToImage);
                  })),
    );
  }
}

【讨论】:

    【解决方案2】:

    已经由其他人完成。 但我尝试上传代码。

    有一些问题。

    • fetchAricle 方法只获取一篇文章。

    所以我改为从 url 获取文章。 使用“FutureBuilder”只需构建一个包含文章的列表视图。

    import 'dart:convert';
    import 'package:http/http.dart' as http;
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          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> {
      String urlToImage;
      Future<List<Article>> newslist;
    
      Future<List<Article>> fetchArticle() async {
        var url =
            'http://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=2e8e3846c42a4f64a6b1d98370bdeeea';
    
        final response = await http.get(url);
    
        if (response.statusCode == 200) {
          var data = json.decode(response.body);
          List<Article> listArticle = data["articles"].map<Article>((article) {
            return Article.fromJson(article);
          }).toList();
          return listArticle;
        } else {
          throw Exception('Failed to load Article');
        }
      }
    
      @override
      void initState() {
        super.initState();
        newslist = fetchArticle();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Api calls',
          home: Scaffold(
            appBar: AppBar(
              title: Text('Api Calls'),
            ),
            body: FutureBuilder<List<Article>>(
              future: newslist,
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  // return Container();
                  return ListView.builder(
                    shrinkWrap: true,
                    itemCount: snapshot.data.length,
                    itemBuilder: (context, index) {
                      return Image.network(snapshot.data[index].urlToImage);
                    },
                  );
                } else if (snapshot.hasError) {
                  return Text("${snapshot.error}");
                }
                return Container();
              },
            ),
          ),
        );
      }
    
      Widget _buildBody() {
        return Container();
      }
    }
    
    class Article {
      final String author;
      final String title;
      final String description;
      final String publishedAt;
      final String urlToImage;
      final String url;
    
      Article(
          {this.author,
          this.description,
          this.title,
          this.publishedAt,
          this.urlToImage,
          this.url});
    
      factory Article.fromJson(Map<String, dynamic> json) {
        return Article(
            author: json['author'],
            title: json['title'],
            description: json['description'],
            publishedAt: json['publishedAt'],
            url: json['url'],
            urlToImage: json['urlToImage']);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-09
      • 2013-09-02
      • 2021-02-24
      • 2021-02-18
      • 1970-01-01
      • 1970-01-01
      • 2020-03-13
      • 1970-01-01
      相关资源
      最近更新 更多