Pendahuluan
Masyarakat dunia digemparkan dengan penyebaran makhluk 'tak kasat mata' yang telah menyebabkan ribuan korban meregang nyawa dalam yang tempo yang relatif singkat. Orang-orang panik, penyebaran informasi yang kian massive dilakukan untuk memberikan peringatan kepada khalayak ramai agar berhati-hati dalam berinteraksi di ruang publik demi meminimalisir penyebaran virus ini yang juga tak kalah cepatnya dari internet 4G.
Setiap orang berusaha mengambil andil dalam berkontribusi untuk melawan Covid-19, tidak terlepas para programmer ramai membuat apps untuk pelacakan dan persebaran infeksi yang sudah terjadi. Melalui artikel kali ini, kita akan membahas bagaimana membuat aplikasi tracking Covid-19 menggunakan Flutter.
Aplikasi Tracking Covid-19
Sebelum memulai mengerjakan aplikasi tracking ini, kita harus menganalisis data yang akan digunakan agar benar-benar valid dan tidak menimbulkan hoax di tengah masyarakat. Adapun sumber yang akan kita gunakan adalah site kawalcovid19 sebagai acuan untuk data penyebaran di Indonesia dan kawalcorona untuk data penyebaran di Dunia. Adapun aplikasi yang akan kita buat kurang lebih terlihat seperti gambar berikut
Untuk memulainya, install Flutter terlebih dahulu dengan command
flutter create dw_corona
Tunggu hingga proses instalasi selesai dan selanjutnya kita akan meng-install beberapa package yang dibutuhkan, diantaranya adalah http dan provider. Buka file pubspec.yaml
dan tambahkan dua baris berikut tepat dibawah cupertino_icons
provider: ^4.0.4
http: ^0.12.0+4
Jika menggunakan VsCode maka akan secara otomatis mengunduh, tapi kita bisa melakukan secara manual dengan menjalankan command flutter pub get
.
Buka file main.dart
untuk membuat kerangka aplikasi kiat dan modifikasi menjadi
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import './providers/corona_provider.dart';
import './home.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//PROVIDER DIGUNAKAN UNTUK MANAJEMEN STATE, PEMBAHASAN LEBIH LENGKAP ADA DI ARTIKEL BERBEDA
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => CoronaProvider(),
)
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Home(),
title: 'Corona - Daengweb.id',
),
);
}
}
Ada dua file yang harus di-import, pertama adalah corona_provider.dart
dan yang kedua adalah home.dart
. Buat file corona_provider.dart
untuk meng-handle seluruh state dan action ke API, kemudian tempatkan ke dalam folder lib/providers
.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import './indonesia_model.dart';
import './world_model.dart';
class CoronaProvider with ChangeNotifier {
IndonesiaModel summary; //STATE UNTUK MENAMPUNG DATA DI INDONESIA
WorldModel world; //STATE UNTUK MENAMPUNG DATA DUNIA
String updated; //STATE UNTUK MENAMPUNG WAKTU PEMBAHARUAN
//FUNGSI INI AKAN MENJALANKAN API CALL UNTUK MENGAMBIL DATA
Future<void> getData() async {
//BAGIAN PERTAMA ADALAH UNTUK MENGAMBIL DATA DARI INDONESIA
final url = 'https://kawalcovid19.harippe.id/api/summary';
final response = await http.get(url); //HIT KE API
//DAN CONVERT DATA YANG DITERIMA
final result = json.decode(response.body) as Map<String, dynamic>;
//LALU MASUKKAN KE DALAM STATE SUMMARY DENGAN FORMAT BERDASARKAN INDONESIAMODEL
summary = IndonesiaModel(
confirmed: result['confirmed']['value'],
recovered: result['recovered']['value'],
deaths: result['deaths']['value'],
activeCare: result['activeCare']['value'],
);
//SIMPAN DATA PEMBAHARUAN KE DALAM STATE UPDATED
updated = result['metadata']['lastUpdatedAt'];
//ADAPUN DATA DUNIA MEMILIKI 3 BUAH API, DAN MASING-MASING MENGHASILKAN DATANYA SENDIRI.
//ADAPUN PENJELASANNYA SAMA DENGAN PENJELASAN SEBELUMNYA
final worldPositive = 'https://api.kawalcorona.com/positif/';
final responsePositive = await http.get(worldPositive);
final resultPositive = json.decode(responsePositive.body);
final worldRecovered = 'https://api.kawalcorona.com/sembuh/';
final responseRecovered = await http.get(worldRecovered);
final resultRecovered = json.decode(responseRecovered.body);
final worldDeaths = 'https://api.kawalcorona.com/meninggal/';
final responseDeaths = await http.get(worldDeaths);
final resultDeaths = json.decode(responseDeaths.body);
world = WorldModel(
confirmed: resultPositive['value'],
deaths: resultRecovered['value'],
recovered: resultDeaths['value'],
);
notifyListeners(); //INFORMASIKAN BAHWA TERJADI PERUBAHAN STATE AGAR WIDGET DIRENDER ULANG
}
}
Perhatikan kembali pada file di atas, kita perlu meng-import dua buah file baru bernama indonesia_model.dart
dan world_model.dart
. Buat file baru bernama indonesia_model.dart
dan tempatkan ke dalam folder yang sama yakni lib/providers
class IndonesiaModel {
final int confirmed;
final int recovered;
final int deaths;
final int activeCare;
IndonesiaModel({this.confirmed, this.recovered, this.deaths, this.activeCare});
}
Selanjutnya buat file baru bernama world_model.dart
import 'package:flutter/material.dart';
class WorldModel {
final String confirmed;
final String recovered;
final String deaths;
WorldModel({
@required this.confirmed,
@required this.recovered,
@required this.deaths,
});
}
Persoalan manajemen data sudah selesai, tahap selanjutnya adalah membuat fungsi untuk menampilkan data-data tersebut ke dalam sebuah widget. Buat file baru bernama home.dart
dan tempatkan di dalam folder lib
import 'package:flutter/material.dart';
import './components/indonesia.dart';
import './components/world.dart';
import 'package:provider/provider.dart';
import './providers/corona_provider.dart';
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height; //KITA AMBIL UKURAN LAYAR
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.pinkAccent,
title: const Text('Lawan Covid19 - [Daengweb.id]'),
),
//PENERAPAN REFRESH INDICATOR AGAR KETIKA LAYAR DITARIK DARI ATAS KE BAWAH, MAKA SECARA OTOMATIS AKAN MELOAD DATA BARU
body: RefreshIndicator(
//MENGGUNAKAN ATTRIBUTENYA YAKNI ONREFRESH
//DAN AKAN MEMANGGIL FUNGSI GETDATA YANG SUDAH DIBUAT PADA CORONA PROVIDER
onRefresh: () =>
Provider.of<CoronaProvider>(context, listen: false).getData(),
child: Container(
margin: const EdgeInsets.all(10),
//KEMUDIAN KETIKA APPS DIBUKA, MAKA FUNGSI FUTURE BUILDER AKAN DIJALANKAN
child: FutureBuilder(
//DAN MELOAD DATA DARI API MENGGUNAKAN FUNGSI YANG SAMA
future:
Provider.of<CoronaProvider>(context, listen: false).getData(),
builder: (context, snapshot) {
//JIKA MASIH LOADING
if (snapshot.connectionState == ConnectionState.waiting) {
//MAKA TAMPILKAN LOADING INDIKATOR
return Center(
child: CircularProgressIndicator(),
);
}
//SELAIN ITU MAKA AKAN KITA TAMPILKAN WIDGET UNTUK DATA
//KITA GUNAKAN CONSUMER UNTUK MENGAMBIL DATA DARI CORONA PROVIDER
return Consumer<CoronaProvider>(
builder: (context, data, _) {
//DIMANA ADA DUA BUAH COLUMN
return Column(
children: <Widget>[
//YANG PERTAMA ADALAH DATA INDONESIA YANG WIDGETNYA KITA PISAHKAN KE FILE TERSENDIRI
Flexible(
flex: 1,
child: Indonesia(height: height, data: data,),
),
//DAN YANG KEDUA ADALAH WIDGET UNTUK MENAMPILKAN DATA DUNIA DENGAN CARA YANG SAMA
Flexible(
flex: 1,
child: World(height: height, data: data,),
)
],
);
},
);
},
),
),
),
);
}
}
Ada dua buah file baru yang di-import dimana berperan untuk menampilkan datanya masing-masing, tujuan pemisahan file-nya agar lebih mudah di-handle ketika proses development. Buat file baru bernama indonesia.dart
dan tempatkan ke dalam folder lib/components
import 'package:flutter/material.dart';
import '../widgets/summary_card.dart';
class Indonesia extends StatelessWidget {
final double height;
final data;
Indonesia({this.height, this.data}); //TERIMA DATA YANG DIKIRIMKAN KETIKA COMPONENT INDONESIA DIGUNAKAN OLEH HOME.DART
@override
Widget build(BuildContext context) {
//PISAHKAN LAGI MENJADI DUA BUAH KOLOM
return Column(
children: <Widget>[
//BAGIAN PERTAMA ADALAH HEADINGNYA
Padding(
padding: const EdgeInsets.only(top: 10.0, bottom: 5.0),
child: const Text(
'LAPORAN JUMLAH KASUS DI INDONESIA',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
Divider(),
//BAGIAN INI ADALAH MASING-MASING DATANYA
Expanded(
flex: 2,
//YANG AKAN DITAMPILKAN MENGGUNAKAN GRIDVIEW
child: GridView.count(
childAspectRatio: height / 350, //DENGAN RASIO TINGGI LAYAR BAGI 350
crossAxisCount: 2, //HANYA ADA DUA WIDGET DALAM SATU DERETAN
crossAxisSpacing: 10, //INI UNTUK JARAK MASING-MASING WIDGET
mainAxisSpacing: 10,
children: <Widget>[
//ADAPUN CARD YANG AKAN MERENDER DATANYA KITA PISAHKAN LAGI KE COMPONENT SENDIRI
//DIMANA DATA YANG DIKIRIMKAN ADALAH TOTAL, LABEL, WARNA DAN UKURAN HURUFNYA
SummaryCard(
total: data.summary.confirmed.toString(),
label: 'Terkonfirmasi',
color: Colors.yellowAccent[100],
size: 35,
),
SummaryCard(
total: data.summary.activeCare.toString(),
label: 'Dalam Perawatan',
color: Colors.purple[100],
size: 35,
),
SummaryCard(
total: data.summary.recovered.toString(),
label: 'Sembuh',
color: Colors.greenAccent[100],
size: 35,
),
SummaryCard(
total: data.summary.deaths.toString(),
label: 'Meninggal',
color: Colors.red[300],
size: 35,
),
],
),
),
],
);
}
}
Kemudian buat lagi file yang baru bernama world.dart
dengan folder yang sama, yakni lib/components
import 'package:flutter/material.dart';
import '../widgets/summary_card.dart';
class World extends StatelessWidget {
final double height;
final data;
World({this.height, this.data});
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 15, bottom: 5),
child: const Text(
'LAPORAN KASUS DUNIA',
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
Expanded(
flex: 1,
child: GridView.count(
crossAxisCount: 3,
childAspectRatio: height / 430,
children: <Widget>[
SummaryCard(
total: data.world.confirmed,
label: 'Positif',
color: Colors.yellow[100],
size: 20,
),
SummaryCard(
total: data.world.recovered,
label: 'Sembuh',
color: Colors.greenAccent[100],
size: 20,
),
SummaryCard(
total: data.world.deaths,
label: 'Meninggal',
color: Colors.red[300],
size: 20,
),
],
),
),
Text('Pembaruan Terakhir'),
Text(data.updated),
],
);
}
}
Note: Penjelasan dari code di atas hampir sama dengan penjelasan sebelumnya.
Bagian terakhir adalah components SummaryCard(), dimana bagian ini berisi card beserta text yang akan ditampilkan. Buat file summary_card.dart
di dalam folder lib/widgets
dan tambahkan code
import 'package:flutter/material.dart';
class SummaryCard extends StatelessWidget {
final String total;
final String label;
final Color color;
final int size;
//HANDLE DATA YANG DIKIRIMKAN
SummaryCard({
@required this.total,
@required this.label,
@required this.color,
@required this.size
});
@override
Widget build(BuildContext context) {
return Card(
color: color, //WARNA CARD BERDASARKAN WARNA YANG DITERIMA
//LALU CHILDNYA KITA BAGI DUA MENGGUNAKAN KOLOM
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//YANG PERTAMA ADALAH TOTAL DATA
Text(
total,
style: TextStyle(
fontSize: size.toDouble(),
fontWeight: FontWeight.bold,
),
),
//DAN YANG KEDUA ADALAH LABEL DATA
Text(
label,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
)
],
),
elevation: 5,
);
}
}
Kesimpulan
Mekanisme pembuatan aplikasi tracking pada materi ini terbilang sangat sederhana, adapun penjelasan detail dari masing-masing widget dan package yang digunakan sudah dibahas pada mater Flutter sebelumnya.
Harapan kita bersama semoga virus ini bisa segera berakhir dan mengembalikan rutinitas masyarakat Indonesia seperti sedia kala.
Comments