Pada modul ini dibahas cara untuk mendapatkan data dari Web API menggunakan package HTTP dari flutter. Web API menyediakan data yang dapat diakses oleh publik menggunakan perangkat mobile maupun web. Data yang disajikan oleh Web API dalam format JSON (Javascript Object Notation). Format JSON dalam API sangat disukai dikarenakan sederhana, mudah digunakan, dan memiliki ukuran yang kecil.
Data API dalam Format JSON
Data API yang akan kita tampilkan pada layar smartphone adalah dari Random Quote, dan List Quote. Data menggunakan format JSON, kita dapat menghasil datanya pada tautan berikut :
- Random Quote (quote-api.dicoding.dev/random)
- List Quote (quote-api.dicoding.dev/list)
Format Penulisan Random Quote dan List Quote ditunjukan gambar berikut.
Pada format JSON, data dibungkus menggunakan dua kurung
- Kurung Siku [ ] dinyatakan sebagai JSON Array yang biasanya kumpulan data yang berbentuk Objel
- Kurung Kurawal { } dinyatakan sebagai JSON objek. Data yang ada pada JSON objek berisi informasi dalam bentuk key dan value
Latihan Mengambil Data dari API
Sebagai bahan latihan, kita akan membuat aplikasi Random Quote yang akan menampilkan Quote beserta Penciptanya.
- Buat Project Flutter Baru pada visual studio code, dengan menekan shortcut (CTRL + SHIFT + P). Beri nama projek dengan “random_quote_api“. Atau bisa juga menggunakan Command Promp (CMD) dengan mengetikan perintah :
$ flutter create random_quote_api
- Tambahkan package http agar aplikasi kita dapat melakukan parsing JSON. Tambahkan kode berikut pada file pubspec.yaml
http: ^0.13.5
Setelah ditambahkan, harap simpan dengan menekan shortcup CTRL + S atau gunakan perintah$ flutter pub get
- Buat 2 file dart bernama listquote.dart dan randomquote.dart di dalam folder lib
- randomquote.dart berfungsi untuk menampilkan data quote secara random
- listquote.dart berfungsi untuk menampilkan kumpulan quote
- Tambahkan kode berikut pada file randomquote.dart
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:belajar_api/listquote.dart'; import 'dart:convert'; class RandomQuote extends StatelessWidget { final String apiUrl = "https://quote-api.dicoding.dev/random"; const RandomQuote({super.key}); Future<dynamic> _fecthRandomQuotes() async { var result = await http.get(Uri.parse(apiUrl)); return json.decode(result.body); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Random Quotes'), ), body: FutureBuilder<dynamic>( future: _fecthRandomQuotes(), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData) { return Center( child: Container( padding: const EdgeInsets.all(20), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Column( children: [ Text( snapshot.data['en'], style: const TextStyle(fontSize: 20), textAlign: TextAlign.center, ), const SizedBox(height: 16), // ignore: prefer_interpolation_to_compose_strings Text( // ignore: prefer_interpolation_to_compose_strings "~ " + snapshot.data['author'], style: const TextStyle( fontSize: 15, fontStyle: FontStyle.italic), textAlign: TextAlign.center, ), ], ), Align( alignment: Alignment.bottomCenter, child: SizedBox( width: 110, height: 35, child: ElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const ListQuote(), ), ); }, child: const Text('List Quote', style: TextStyle(fontSize: 16)), ), ), ), ], ), ), ); } else { return const Center(child: CircularProgressIndicator()); } }, ), ); } }
- Kemudian tambahkan kode pada file listquote.dart, sehingga isi dari file listquote.dart adalah sebagai berikut
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'dart:convert'; class ListQuote extends StatelessWidget { final String apiUrl = "https://quote-api.dicoding.dev/list"; const ListQuote({super.key}); Future<List<dynamic>> _fecthListQuotes() async { var result = await http.get(Uri.parse(apiUrl)); return json.decode(result.body); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('List of Quotes'), ), body: FutureBuilder<List<dynamic>>( future: _fecthListQuotes(), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData) { return ListView.builder( padding: const EdgeInsets.all(10), itemCount: snapshot.data.length, itemBuilder: (BuildContext context, int index) { return Card( child: ListTile( title: Text( snapshot.data[index]['en'], textAlign: TextAlign.justify, ), subtitle: Text( // ignore: prefer_interpolation_to_compose_strings "\n~ " + snapshot.data[index]['author'], style: const TextStyle(fontStyle: FontStyle.italic), ), trailing: Flexible( child: SizedBox( width: 60, child: Row( children: [ RatingBar.builder( minRating: 1, itemCount: 1, allowHalfRating: true, onRatingUpdate: (double value) {}, initialRating: 4.7, itemBuilder: (context, _) => const Icon( Icons.star, color: Colors.redAccent, ), ), Text(snapshot.data[index]['rating'].toString()) ], ), ), ), ), ); }); } else { return const Center(child: CircularProgressIndicator()); } }, ), ); } }
- Apabila terjadi error pada fungsi
RatingBar()
, itu karena kita belum menambahkan widgetflutter_rating_bar
. Oleh karena itu silahkan tambahkan kode berikut pada pubspec.yaml, kemudian tekan save.flutter_rating_bar: ^4.0.1
- Terakhir sesuaikan kode pada file main.dart, sehingga kode lengkapnya menjadi seperti ini
import 'package:belajar_api/randomquote.dart'; import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Belajar API', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.red, ), home: const RandomQuote(), ); } }
- Apabila sudah tidak ada kode yang error, silahkan jalankan aplikasi random quote kita. Sehinga tampilan dari aplikasi kita adalah sebagai berikut.
Mari Kita Ulas kodenya lebih detail
final String apiUrl = "https://quote-api.dicoding.dev/list"; Future<List<dynamic>> _fecthListQuotes() async { var result = await http.get(apiUrl); return json.decode(result.body); }
Fungsi _fecthListQuotes
digunakan untuk memanggil API dari string apiURL menggunakan http.get
. Karena kita ingin menunggu response dari API sebelum melanjutkan ke proses selanjutnya maka kita membutuhkan asynchronous function dengan menambahkan async setelah nama function dan await pada proses yang ingin kita tunggu.
Kemudian, karena kita tidak ingin mengatur output dari response API maka kita cukup gunakan List dengan tipe dynamic List<dynamic>
. Dalam projek rill sebaiknya kita define terlebih dahulu format output dari mulai tipe data dan struktur datanya untuk meminimalisir error dan memudahkan dalam pembacaan data. Penjelasan lebih detail tentang Mapping Object akan kita bahas pada artikel terpisah.
Selain itu karena respon API dalam format JSON, maka kita perlu merubahnya menggunakan json.decode. Untuk menggunakan json.decode wajib import ‘dart:convert’;
import 'dart:convert'; ... ... return json.decode(result.body); ...
Contoh Respon JSON
[ { "id": "5a6ce86e2af929789500e7e4", "sr": "Računarska nauka se tiče računara koliko i astronomija teleskopa.", "en": "Computer Science is no more about computers than astronomy is about telescopes.", "author": "Edsger W. Dijkstra", "rating": 4.2 }, ]
Karena membutuhkan data yang ada dalam JSON Array, maka saat return array nya pun hanya mengambil array data saja (result.body);
FutureBuilder Widget
child: FutureBuilder<List<dynamic>>( future: _fecthListQuotes(), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData) { // Tampilkan List Quote } else { // List quote belum ada, tampilkan animasi loading }
Selanjutnya pada main widget kita gunakan FutureBuilder, yang mana properti future digunakan untuk memanggil fungsi fetchListQuote dan builder untuk menampilkan data API ke UI. Dalam penggunaan FutureBuilder sebaiknya selalu tambahkan pengecekan apakah snapshot sudah memiliki data atau belum agar tampilan tidak error jika gagal atau belum mendapatkan feedback dari API.
Dan terakhir menampilkan data ke dalam ListView
return ListView.builder( padding: EdgeInsets.all(10), itemCount: snapshot.data.length, itemBuilder: (BuildContext context, int index) { return ListTile( ...
Penutup
HTTP Get dalam flutter dapat dilakukan dengan cara sederhana yang sama seperti di atas, tetapi contoh ini hanyalah sebuah konsep. Lebih disarankan untuk melakukan modifikasi, seperti mapping untuk setiap objek keluaran, dan memisahkan widget panggilan API dari widget utama. Permintaan HTTP tidak hanya metode GET tetapi juga metode lain seperti POST, PATCH, PUT, DELETE dan lainnya.
Semoga Bermanfaat 🙂