Getting data from an API in flutter

56 Views Asked by At

Tring to fetch data using API

My code

class _MyAppState extends State<MyApp> {
  Future<News> news;

  @override
  void initState() {
    super.initState();
    news = fetchNews();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: 
      Container(
        color: Colors.white24,
        child:
        Center(child:
        FutureBuilder<News>(
  future: fetchNews(),
  builder: (context, snapshot) {
    if (snapshot.hasData) {

        /* here if I removed toString() it gives me error
         The argument type 'News' can't be assigned to the parameter type 
         'String'. */ 

       return Text(snapshot.data.toString());
    } else if (snapshot.hasError) {
      return Text("${snapshot.error}");
    }

    // By default, show a loading spinner.
    return CircularProgressIndicator();
            },
           ),
          ),
         )
        );
       }
      }
News newsFromJson(String str) => News.fromJson(json.decode(str));

String newsToJson(News data) => json.encode(data.toJson());

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

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

    factory News.fromJson(Map<String, dynamic> json) => News(
        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"] == null ? null : json["author"],
        title: json["title"],
        description: json["description"] == null ? null : json["description"],
        url: json["url"],
        urlToImage: json["urlToImage"] == null ? null : json["urlToImage"],
        publishedAt: DateTime.parse(json["publishedAt"]),
        content: json["content"],
    );

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

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

    dynamic id;
    String name;

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

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

Future<News> fetchNews() async {
  final response = await http.get('My-Api');

  if (response.statusCode == 200) {
    
    return News.fromJson(jsonDecode(response.body));
  } else {
    
    throw Exception('Failed to load album');
  }
}

when I run this Code the output is : Instance of 'News'

I searched the internet and found most solutions saying I must add await.

The only problem is THEY DON'T SAY WHERE SHOULD I PUT IT EXACTLY IN THE CODE

Your help will be appreciated,

Thank you

Note: I'm still a beginner

1

There are 1 best solutions below

1
On BEST ANSWER

You don't need to add await. Your code is working correctly. The only thing I would change is

FutureBuilder<News>(
   future: fetchNews(),

to

FutureBuilder<News>(
   future: news,

Here is a very good explanation for this.

Your output Instance of 'News' is correct. It's the model you declared for the output of your network call. You now have access to it's properties (status, totalResults and articles).

/* here if I removed toString() it gives me error The argument type 'News' can't be assigned to the parameter type 'String'. */

That's because the Text widget expects his input to be of typ String and not of type News.