3

I want to create a news app and I've used newsapi.org as a source.

I am trying to fetch the JSON data coming by the Http library.

I've provided the entire code below.

It doesn't give me any error but no data loaded and when I print the data it prints everything okay but I can't display it.

I don't what is the problem but all my project has stopped on this problem.

I am looking for a solution for this code because it doesn't work.

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:newly/services/networking.dart';
import 'package:newly/widgets/article.dart';

class NewsScreen extends StatefulWidget {
  @override
  _NewsScreenState createState() => _NewsScreenState();
}

class _NewsScreenState extends State<NewsScreen> {

  List<Article> articles = [];

  NetworkHelper networkHelper = NetworkHelper(
    url:
        'https://newsapi.org/v2/everything?q=bitcoin&apiKey=392495172bab4b3885ae93760df54b91',
  );

  Future<List<Widget>> getNews() async {
    var newsData = await networkHelper.getData();

    for (int i = 0; i < await newsData['articles'].length; i++) {
      var title = await newsData['articles'][i]['title'];
      var urlToImage = await newsData['articles'][i]['urlToImage'];
      var content = await newsData['articles'][i]['content'];
      var author = await newsData['articles'][i]['author'];
      var url = await newsData['articles'][i]['url'];

      print(title);
      print(urlToImage);
      print(url);
      print(content);
      print(author);
      print('123456789123456789123456789123456789');

      articles.add(
        Article(
          author: author,
          content: content,
          title: title,
          url: url,
          urlToImage: urlToImage,
        ),
      );

      print(articles[0].author);

    }

    return articles;
  }

  Future<List<Article>> showArticles() async {
    var data = await get(
      'https://newsapi.org/v2/everything?q=bitcoin&apiKey=392495172bab4b3885ae93760df54b91',
    );

    var dataDecoded = await json.decode(data.body);

    List<Article> articles = [];

    await dataDecoded.forEach(
      (article) {
        articles.add(
          Article(
            author: article['author'],
            content: article['content'],
            title: article['title'],
            url: article['url'],
            urlToImage: article['urlToImage'],
          ),
        );
      },
    );

    return articles;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        centerTitle: true,
        title: Text(
          'Newly',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: FutureBuilder(
        future: getNews(),
        builder: (context, snapshot) {
          return ListView(
            children: articles,
          );
        },
      ),

    );
  }
}

Network Helper :

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

class NetworkHelper {
  NetworkHelper({this.url});

  final String url;

  Future getData() async {
    http.Response response = await http.get(url);

    if (response.statusCode == 200) {
      String data = response.body;

      return json.decode(data);
    } else {
      print('something wrong');
      print(response.statusCode);
    }
  }
}
3
  • can you please show your NetworkHelper class? Commented Nov 5, 2019 at 7:09
  • I've updated now Commented Nov 5, 2019 at 7:20
  • Okay I will answer it Commented Nov 5, 2019 at 7:26

4 Answers 4

10

While working with json data

The good practice is to create a model for that and then just fetch the data through the api

creating a model and a class is easy enough and doesn't take effort and makes your work easy ;)

For creating a model for your project

VISIT https://javiercbk.github.io/json_to_dart/

just copy your json data and paste in the textField and you will get your Model Class ready with just one click

for accessing the data

Test _test = Test.fromJson(response.body);

that's it.

refer image shown below

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

easy approach to convert model of response.
but still not getting data from response same error - the method '[]' was called on null. E/flutter ( 8569): Receiver: null
@s.j the error reflects that from api end you are not getting any data, or may be you are not accessing it properly. Try to check the response first
5

The problem is in showing the articles. and yaa also as @ISpam Ossama says, you have to use setState for adding the data to list like this.

void getNews() async {
var newsData = await networkHelper.getData();

for (int i = 0; i < newsData['articles'].length; i++) {
  var title = newsData['articles'][i]['title'];
  var urlToImage = newsData['articles'][i]['urlToImage'];
  var content = newsData['articles'][i]['content'];
  var author = newsData['articles'][i]['author'];
  var url = newsData['articles'][i]['url'];

  print(title);
  print(urlToImage);
  print(url);
  print(content);
  print(author);
  print('123456789123456789123456789123456789');
  setState(() {
   articles.add(
    Article(
      author: author,
      content: content,
      title: title,
      url: url,
      urlToImage: urlToImage,
    ),
  );
  });
  print(articles[0].author);
}
}

Now, you have to display the articles like this.

ListView.builder(
          itemCount: articles.length,
          itemBuilder: (BuildContext ctxt, int index) {
            return Text(articles[index].title);
          },
        )

Hope it will help you!

6 Comments

why are you use await in all statement ? Like, await newsData['articles'][i]['title'];
And also issue in setstate. because if we are getting 1000 data, then Widget will rebuild 1000 times. It should outside of for loop.
Yes you are right, I am really very sorry, I didn't noticed it, i will update the answer
I understood the await issue, but what is the alternate solution of the setState?
first add all data in local array and then setstate with global after for loop.
|
2

Try to setState before adding the articles to the array

Comments

1

You can also do it using FutureBuilder , If you want otherwise as @Mustafa answer will work.

Future<List<Article>> showArticles() async {
var data = await networkHelper.getData();

List<Article> articlesArr = [];

await data['articles'].forEach(
  (article) {
    articlesArr.add(
      Article(
        author: article['author'],
        content: article['content'],
        title: article['title'],
        url: article['url'],
        urlToImage: article['urlToImage'],
      ),
    );
  },
);
return articlesArr;
}

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        centerTitle: true,
        title: Text(
          'Newly',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: FutureBuilder<List<Article>>(
        future: showArticles(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView(
              children: snapshot.data.map((article) {
                return Container(
                  padding: EdgeInsets.all(8.0),
                  child: Text(article.author),
                );
              }).toList(),
            );
          } else {
            return Container(
              color: Colors.blue,
            );
          }
        },
      ),
    );
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.