Build a Flutter News App with News API

Nadilla C. Putri
7 min readAug 13, 2021

Bismillah,
Hai guys di story pertamaku ini kita akan membahas tentang cara membuat aplikasi berita menggunakan API dari newsapi.org . Dan untuk membuat aplikasi ini kita membutuhkan Plugin HTTP agar bisa mengambil data dari newsapi.org.

Apa itu HTTP ?
HTTP atau Hypertext Transfer Protocol bisa disebut sebagai alat komunikasinya client dan server. Jadi, HTTP ini dirancang untuk memungkinkan client dan server untuk saling berkomunikasi, seperti request dan response data. Jika dillustrasikan, komunikasi antara client dan server dapat kita lihat seperti gambar berikut ini :

source : hackernoon.com

Method pada HTTP

  1. GET
    Method ini digunakan untuk mengambil atau me-request data dari server. contohnya seperti menampilkan data pada aplikasi dimana data tersebut bersumber dari server.
  2. POST
    Biasa digunakan untuk mengirim atau menyimpan data pada server, seperti jika kita ingin menambahkan data pada suatu server kita dapat menggunakan method ini untuk perintah tersebut.
  3. PUT
    Method PUT digunakan untuk mengupdate atau melakukan perubahan pada sever.
  4. DELETE
    Sama hal dengan namanya, method ini digunaka ketika kita ingin menghapus data pada server.

Sekian sekilas penjelasan dari HTTP, selanjutnya kita akan mengimplementasikannya pada Aplikasi Berita menggunakan bahasa Pemrograman Flutter dimana datanya bersumber dari API yang disediakan oleh newsapi.org .

Untuk menggunakan NEWSAPI kita harus login terlebih dahulu untuk mendapatkan API Keys dari API nya di newsapi.org

Sebelum mengimplementasikan newsapi, terlebih dahulu kita membuat UI nya terlebih dahulu pada file home.dart

UI LIST

Pada UI List ini kita menggunakan ListView untuk menampilkan data, berikut struktur widget yang kita gunakan untuk menampilkan List.

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: new Center(
child: Text('News App', style: TextStyle(color: Colors.black))),
backgroundColor: Colors.white,
),
body: ListView.builder(
itemCount: _post.length,
itemBuilder: (context, index) {
return ListTile(
leading: Container(
color: Colors.grey[200],
height: 100,
width: 100,
),
title: Text(
'Title',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(
'Description',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
onTap: () {
},
);
},
),
);
}

Setelah membuat UI untuk List Berita, selanjutnya kita dapat memanggil data yang disediakan oleh newsapi.org dengan menggunakan HTTP. Untuk menggunakan komponen ini, kita harus menambahkan plugin HTTP pada dependecies di pubspec.yml dan jangan lupa untuk klik Pub Get.

dependencies:
flutter:
sdk: flutter
http: ^0.13.3

Sebelum lanjut membuat UI untuk Detail Berita, kita dapat implementasikan terlebih dahulu pemanggilan data JSON dari newsapi.org

  1. Pertama-tama tambahkan variable List yang bernama _get pada main class Home Page untuk menyimpan data yang diambil dari newsapi dan pada initState tambahkan pemanggilan function getData() .
class _HomePageState extends State<HomePage> {
List _get = [];

@override
void initState() {
// TODO: implement initState
super.initState();
_getData();
}

2. Selanjutnya kita dapat membuat function _getData() seperti berikut:

Future _getData() async {
try {
final response = await http.get(Uri.parse(
"https://newsapi.org/v2/everything?q=tesla&from=2021-07-13&sortBy=publishedAt&apiKey=be14be3a5ea949858c0c15edca7cd40d"));
// return jsonDecode(response.body);

// untuk cek data
if (response.statusCode == 200) {
print(response.body);
final data = jsonDecode(response.body);
setState(() {
_get = data['articles'];

});
}
} catch (e) {
print(e);
}
}

Pada code diatas jika data berhasil diambil dari API maka data tersebut akan ditampilkan pada console dan selanjutnya akan disimpan pada variabel “data”. Selanjutnya isi atau body dari data yang diambil akan dikembalikan berupa data JSON yang sudah di decode. Setelah itu, data yang berparameter ‘articles’ disimpan pada variabel _get yang sudah kita deklarasikan pada class main tadi. Function _getData() ini akan secara otomatis berjalan karena kita tambahkan pada initState().

4. Setelah itu, jagan lupa untuk memanggil parameter yang akan ditampilkan pada List. Sesuai dengan UI yang telah kita buat sebelumnya data yang akan kita tampilkan adalah gambar, judul dan deskripsi. Untuk menampilkan gambar kita menggunakan parameter urlToImage dari variabel _get yang yang kita panggil pada widget Container, yang mana jika data urlToImage tidak tersedia atau null maka yang tampil hanya Container. Selanjutnya untuk menampilkan judul berita digunakan parameter title dan deksripsi kita menggunakan parameter description.

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: new Center(
child: Text('News App', style: TextStyle(color: Colors.black))),
backgroundColor: Colors.white,
),
body: ListView.builder(
itemCount: _get.length,
itemBuilder: (context, index) {
return ListTile(
leading: Container(
color: Colors.grey[200],
height: 100,
width: 100,
child: _get[index]['urlToImage'] != null
? Image.network(
_get[index]['urlToImage'],
width: 100,
fit: BoxFit.cover,
)
: Center(),
),
title: Text(
'${_get[index]['title']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(
'${_get[index]['description']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),

4. Jadi ketika aplikasi di jalankan, maka program akan langsung melakukan get data pada API, sehingga data berita dapat tampil seperti berikut :

Jika data tersebut tidak berhasil didapatkan maka pesan errornya akan di print pada terminal.

Terakhir, pada properti onTap di widget HomePage kita akan menggunakan Navigator.push untuk perpindahan halaman dari HomePage ke PageDetail. Dan ketika perpindahan dari HomePage ke PageDetail kita akan membawa data yang akan kita tampilkan di PageDetail yaitu url, title, content, dan urlToImage, author, dan publishedAt.

onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (c) => DetailPage(
url: _get[index]['url'],
title: _get[index]['title'],
content: _get[index]['content'],
urlToImage: _get[index]['urlToImage'],
author: _get[index]['author'],
publishedAt: _get[index]['publishedAt'],
),
),
);

5. Selanjutnya, kita membuat UI dari Detail Berita pada file baru, dengan cara klik kanan pada package lib>New>New Dart File, dengan nama file detail_berita.dart. Lalu kita tambahka widget berikut untuk menampilkan detail berita.

Pada file detail_berita.dart ini kita akan menambahkan UI sekaligus kodingan untuk menampilkan detail berita ketika salah satu berita kita klik pada list berita. Berikut kodingan untuk detail berita :
6. Tambahkan variable untuk menyimpan data yang dikirim dari HomePage, seperti berikut:

class DetailPage extends StatelessWidget {

final url,title,content,publishedAt,author,urlToImage;

DetailPage({this.title="",
this.url="",
this.content,
this.publishedAt,
this.author,
this.urlToImage});

7. Selanjutnya, pada widget DetailPage kita akan menambahkan variabel yang telah kita deklarasikan pada class main DetailPage seperti berikut:

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar( backgroundColor: Colors.white,
title: new Center(child:Text("Detail", style: TextStyle(color: Colors.black),),),
automaticallyImplyLeading: false,
),
body: Column(
children: <Widget>[
urlToImage != null ? Image.network(urlToImage):
Container(
margin: EdgeInsets.all(20),
height: 250,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0), color: Colors.grey
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('$title',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
'$publishedAt',
style: TextStyle(fontStyle: FontStyle.italic),
),
SizedBox(
height: 5,
),
Text('$content'),
Divider(),
Text('$author'),
Text('$url'),
],
),
)
],
),
//Floating Action Button
floatingActionButton: FloatingActionButton(
child: Icon(Icons.close),
backgroundColor: Colors.black87,
onPressed: () => Navigator.pop(context),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}

Finally, berikut dilihat secara keseluruhan kodingan dari file home.dart dan detail_page.dart

file home.dart

import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:newsapp/detail.dart';
import 'package:http/http.dart' as http;

class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
List _get = [];

@override
void initState() {
// TODO: implement initState
super.initState();
_getData();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: new Center(
child: Text('News App', style: TextStyle(color: Colors.black))),
backgroundColor: Colors.white,
),
body: ListView.builder(
itemCount: _get.length,
itemBuilder: (context, index) {
return ListTile(
leading: Container(
color: Colors.grey[200],
height: 100,
width: 100,
child: _get[index]['urlToImage'] != null
? Image.network(
_get[index]['urlToImage'],
width: 100,
fit: BoxFit.cover,
)
: Center(),
),
title: Text(
'${_get[index]['title']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(
'${_get[index]['description']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (c) => DetailPage(
url: _get[index]['url'],
title: _get[index]['title'],
content: _get[index]['content'],
urlToImage: _get[index]['urlToImage'],
author: _get[index]['author'],
publishedAt: _get[index]['publishedAt'],
),
),
);
},
);
},
),
);
}

Future _getData() async {
try {
final response = await http.get(Uri.parse(
"https://newsapi.org/v2/everything?q=tesla&from=2021-07-13&sortBy=publishedAt&apiKey=be14be3a5ea949858c0c15edca7cd40d"));
// return jsonDecode(response.body);

// untuk cek data
if (response.statusCode == 200) {
print(response.body);
final data = jsonDecode(response.body);
setState(() {
_get = data['articles'];
});
}
} catch (e) {
print(e);
}
}
}

File detail_page.dart

import 'package:flutter/material.dart';

class DetailPage extends StatelessWidget {

final url,title,content,publishedAt,author,urlToImage;

DetailPage({this.title="",
this.url="",
this.content,
this.publishedAt,
this.author,
this.urlToImage});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar( backgroundColor: Colors.white,
title: new Center(child:Text("Detail", style: TextStyle(color: Colors.black),),),
automaticallyImplyLeading: false,
),
body: Column(
children: <Widget>[
urlToImage != null ? Image.network(urlToImage):
Container(
margin: EdgeInsets.all(20),
height: 250,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0), color: Colors.grey
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('$title',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
'$publishedAt',
style: TextStyle(fontStyle: FontStyle.italic),
),
SizedBox(
height: 5,
),
Text('$content'),
Divider(),
Text('$author'),
Text('$url'),
],
),
)
],
),
//Floating Action Button
floatingActionButton: FloatingActionButton(
child: Icon(Icons.close),
backgroundColor: Colors.black87,
onPressed: () => Navigator.pop(context),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}

Karena yang ditampilkan pertama kali adalah list dari berita, maka yang kita panggil pada file main.dart adalah HomePage.

import 'package:flutter/material.dart';
import 'package:newsapp/home.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
debugShowCheckedModeBanner: false,
);
}
}

Berikut hasil Running dari program diatas:

Semangat Belajar ^.^

--

--