Open In App

Flutter – Building News Reader App

Last Updated : 24 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In today’s fast-paced world, staying informed is essential, and mobile applications have become a popular medium for accessing news. In this article, we’ll guide you through building a News Reader App step by step using Flutter, a powerful and versatile framework for creating cross-platform applications.

Flutter, developed by Google, allows developers to create natively compiled applications for mobile, web, and desktop from a single codebase. In this tutorial, we’ll leverage Flutter to build a News Reader App that fetches real-time news data from the NewsAPI and presents it in an intuitive and user-friendly manner.

Prerequisites

Before we dive into the implementation, make sure Flutter is installed on the system or download it from the official Flutter website. Also, ensure that a code editor is installed, such as Visual Studio Code or Android Studio.

Step-by-Step Implementation

Step 1: Project Setup

Start by creating a new Flutter project using the following command in the terminal or command prompt:

flutter create news_reader_app

Step 2: Add dependencies to Project

From terminal, add http package to project using following command

flutter pub add http url_launcher

Step 3: Import packages

First, we need to import installed packages before using them to avoid errors.

Dart




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


Step 4: News Class

The News class represents a news article with properties like title, image (URL to the article image), content, and url (URL to the full article).

Dart




class News {
    
  final String title;
  final String image;
  final String content;
  final String url;
  
  News({required this.title, required this.image, required this.content, required this.url});
  
  factory News.fromJson(Map<String, dynamic> json) {
    return News(
      title: json['title'],
      image: json['urlToImage'],
      content: json['content'],
      url: json["url"]
    );
  }
}


Step 5: NewsCard Widget

The NewsCard widget is responsible for displaying individual news articles. It uses the ExpansionTile widget to expand and show the article content when tapped. The _launchURL function uses the url_launcher package to open the full article in a web browser if running application on browser, and on emulator browser if running on emulator.

Dart




class NewsCard extends StatelessWidget {
  final News news;
  
  NewsCard({required this.news});
  
  void _launchURL(String url) async {
    final Uri _url = Uri.parse(url);
    if (!await launchUrl(_url,mode: LaunchMode.inAppWebView)) {
       throw 'Could not launch $url';
  }
  }
  
  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.all(8.0),
      child: ExpansionTile(
        leading: Image.network(news.image),
        title: Text(news.title,style: 
        TextStyle(color: Colors.green,fontSize: 16,
        fontWeight: FontWeight.w400),),
        children: <Widget>[
          Padding(
            padding: EdgeInsets.all(10.0),
            child: Text(
              news.content,
              style: TextStyle(fontSize: 16.0),
            ),
          ),
          InkWell(
            child: Text("Read More",style: TextStyle(color: Colors.blue,height: 3),),
            onTap: (){
              _launchURL(news.url);
            }
          )
        ],
      ),
    );
  }
}


Step 6: MyApp Widget

The MyApp widget is the root of our application. It fetches news data from the NewsAPI using an API key and displays the news articles using the ListView.builder widget.

Dart




class _MyAppState extends State<MyApp> {
  
  @override
  void initState() {
    super.initState();
    _getNewsData();
  }
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Gfg News Reader App',
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        backgroundColor: const Color.fromARGB(255, 202, 242, 203),
        appBar: AppBar(
          title: Text('Gfg News Reader App'),
          backgroundColor: Colors.green,
        ),
        body: _news==null ? CircularProgressIndicator() :ListView.builder(
                itemCount: _news.length,
                itemBuilder: (context, index) {
                  return  NewsCard(news: _news[index]);
                },
              ),
      ),
    );
  }
}


Step 7: Fetching News Data

Define The _getNewsData function inside MyApp widget to make an HTTP GET request to the NewsAPI endpoint, processes the JSON response, and populates the _news list with News objects.

Dart




Future<void> _getNewsData() async {
  http.Response newsResponse;
  String apiKey = "YOUR_API_KEY";
  String urlString =
    
  Uri uri = Uri.parse(urlString);
  newsResponse = await http.get(uri);
  
  if (newsResponse.statusCode == 200) {
    Map<String, dynamic> jsonData = json.decode(newsResponse.body);
    if (jsonData['articles'] != null) {
      List<dynamic> articles = jsonData['articles'];
      _news = articles.map((json) => News.fromJson(json)).toList();
    } else {
      throw Exception('No articles found in the response');
    }
  } else {
    throw Exception('Failed to load news');
  }
}


Complete Code

Below is the complete code of news reader app

Dart




import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:core';
import 'package:url_launcher/url_launcher.dart';
  
void main() => runApp(MyApp());
  
class News {
  final String title;
  final String image;
  final String content;
  final String url;
  
  News({required this.title, required this.image, required this.content, required this.url});
  
  factory News.fromJson(Map<String, dynamic> json) {
    return News(
      title: json['title'],
      image: json['urlToImage'],
      content: json['content'],
      url: json["url"]
    );
  }
}
  
class NewsCard extends StatelessWidget {
  final News news;
  
  NewsCard({required this.news});
  
  void _launchURL(String url) async {
    final Uri _url = Uri.parse(url);
    if (!await launchUrl(_url,mode: LaunchMode.inAppWebView)) {
       throw 'Could not launch $url';
  }
  }
  
  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.all(8.0),
      child: ExpansionTile(
        leading: Image.network(news.image),
        title: Text(news.title,style: 
        TextStyle(color: Colors.green,fontSize: 16,
        fontWeight: FontWeight.w400),),
        children: <Widget>[
          Padding(
            padding: EdgeInsets.all(10.0),
            child: Text(
              news.content,
              style: TextStyle(fontSize: 16.0),
            ),
          ),
          InkWell(
            child: Text("Read More",style: TextStyle(color: Colors.blue,height: 3),),
            onTap: (){
              _launchURL(news.url);
            }
          )
        ],
      ),
    );
  }
}
  
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
  
class _MyAppState extends State<MyApp> {
  List<News> _news = [];
  
  @override
  void initState() {
    super.initState();
    _getNewsData();
  }
  
  Future<void> _getNewsData() async {
  http.Response newsResponse;
  String apiKey = "YOUR_API_KEY";
  String urlString =
    
  Uri uri = Uri.parse(urlString);
  newsResponse = await http.get(uri);
  
  if (newsResponse.statusCode == 200) {
    Map<String, dynamic> jsonData = json.decode(newsResponse.body);
    if (jsonData['articles'] != null) {
      List<dynamic> articles = jsonData['articles'];
      _news = articles.map((json) => News.fromJson(json)).toList();
    } else {
      throw Exception('No articles found in the response');
    }
  } else {
    throw Exception('Failed to load news');
  }
}
  
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Gfg News Reader App',
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        backgroundColor: const Color.fromARGB(255, 202, 242, 203),
        appBar: AppBar(
          title: Text('Gfg News Reader App'),
          backgroundColor: Colors.green,
        ),
        body: _news==null ? CircularProgressIndicator() :ListView.builder(
                itemCount: _news.length,
                itemBuilder: (context, index) {
                  return  NewsCard(news: _news[index]);
                },
              ),
      ),
    );
  }
}


How to Run the App

To run the app, make sure you have Flutter installed and an emulator/device set up. Navigate to the project directory using the terminal and run the following command:

flutter run

This command will build and launch the app on your emulator/device.

Output:

Screenshot-(82)-min

Congratulations! You’ve successfully built a News Reader App with Flutter. This app can be further enhanced by adding features such as category filtering, search functionality, or saved articles.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads