Membuat Aplikasi Tracking Covid-19 Flutter

Membuat Aplikasi Tracking Covid-19 Flutter

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

aplikasi tracking covi19

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.

Category:
Share:

Comments