Skip to main content

Tutorial 8: Flutter Model dan Komunikasi dengan Web Service

Pemrograman Berbasis Platform (CSGE602022) - diselenggarakan oleh Fakultas Ilmu Komputer, Universitas Indonesia, Semester Ganjil 2022/2023

Tujuan Pembelajaran

Setelah menyelesaikan tutorial ini, mahasiswa diharapkan untuk:

  • Memahami struktur dan pembuatan model pada Flutter.
  • Memahami cara mengambil, mengolah, dan menampilkan data dari web service.

Model pada Flutter

Pada tutorial kali ini, kita akan membuat sebuah pemanggilan web service hingga menampilkannya ke halaman Flutter yang kita buat. Akan tetapi sebelum melakukan pemanggilan web service, kita perlu mendefinisikan model yang kita gunakan ketika melakukan pemanggilan web service. Model pada Flutter menggunakan prinsip class seperti layaknya yang sudah dipelajari pada DDP2 bagian OOP.

Kode di bawah ini adalah contoh, tidak wajib diikuti, tetapi sangat disarankan dibaca karena konsepnya akan digunakan pada bagian-bagian selanjutnya.

Berikut merupakan contoh class pada Flutter.

class Mobil {
Mobil({
this.id,
this.brand,
this.model
this.color
});

int id;
String brand;
String model;
String color;
}

Catatan: Jika kamu mengalami error saat membuat class, tambahkan keyword required pada setiap parameter class pada bagian constructor.

Sampai saat ini, kita telah berhasil membuat class. Selanjutnya, kita akan menambahkan beberapa kode sehingga terbentuk sebuah model Mobil. Mobil ini merupakan suatu model yang merepresentasikan response dari pemanggilan web service.

Tambahkan import dart convert pada bagian paling atas file.

import 'dart:convert';
...

Pada class Mobil, tambahkan kode berikut.

factory Mobil.fromJson(Map<String, dynamic> json) => Mobil(
id: json["id"],
brand: json["brand"],
model: json["model"],
color: json["color"],
);

Map<String, dynamic> toJson() => {
"id": id,
"brand": brand,
"model": model,
"color": color,
};

Tambahkan kode berikut di luar class Mobil.

Mobil mobilFromJson(String str) => Mobil.fromJson(json.decode(str));
String mobilToJson(Mobil data) => json.encode(data.toJson());

Sehingga kode akhirnya akan seperti berikut untuk menampilkan satu objek Mobil dari web service.

import 'dart:convert';

Mobil mobilFromJson(String str) => Mobil.fromJson(json.decode(str));
String mobilToJson(Mobil data) => json.encode(data.toJson());

class Mobil {
Mobil({
this.id,
this.brand,
this.model,
this.color,
});

int id;
String brand;
String model;
String color;

factory Mobil.fromJson(Map<String, dynamic> json) => Mobil(
id: json["id"],
brand: json["brand"],
model: json["model"],
color: json["color"],
);

Map<String, dynamic> toJson() => {
"id": id,
"brand": brand,
"model": model,
"color": color,
};
}

Penjelasan kode di atas adalah sebagai berikut.

Terdapat beberapa kode-kode tambahan seperti method toJson dan fromJson di dalam class Mobil. Hal tersebut disebabkan ketika kita me-request suatu web service dengan method GET, umumnya kita mendapatkan hasil pemanggilan berupa JSON. Oleh karena itu, kita perlu melakukan konversi data dengan method fromJson agar Flutter mengenali JSON tersebut sebagai objek class Mobil. Selain itu, terdapat juga method toJson yang akan digunakan ketika kita melakukan pengiriman data ke web service (seperti POST atau PUT).

Berikut adalah contoh respons dari web service dengan method GET yang dapat dikonversi ke class model Mobil tersebut.

{
"id": 1,
"brand": "Honda",
"model": "Civic",
"color": "Yellow"
}

Lalu, bagaimana jika respons dari web service berupa kumpulan objek JSON? Sebenarnya sama saja dengan kode di atas, hanya saja terdapat pengubahan pada method mobilFromJson dan mobilToJson.

Kodenya adalah sebagai berikut.

List<Mobil> mobilFromJson(String str) => List<Mobil>.from(json.decode(str).map((mobil) => Mobil.fromJson(mobil)));

String mobilToJson(List<Mobil> data) => json.encode(List<dynamic>.from(data.map((mobil) => mobil.toJson())));

Berikut adalah contoh respons dari web service dengan method GET yang dapat dikonversi ke model Mobil tersebut.

[
{
"id": 1,
"brand": "Honda",
"model": "Civic",
"color": "Yellow"
},
{
"id": 2,
"brand": "Toyota",
"model": "Supra",
"color": "Red"
}
]

Fetch Data dari Web Service pada Flutter

Sebagai seorang developer, tentunya kita membutuhkan data untuk ditampilkan ke client. Hal ini mengharuskan kalian untuk mengetahui bagaimana cara untuk melakukan fetching data dari web service kemudian menampilkannya ke aplikasi yang telah kita buat sebelumnya.

Secara umum terdapat beberapa langkah ketika ingin menampilkan data dari web service lain ke aplikasi Flutter, yaitu:

  1. Menambahkan dependency http ke proyek, dependency ini digunakan untuk bertukar data melalui HTTP request, seperti GET, POST, PUT, dan lain-lain.

  2. Membuat model sesuai dengan respons dari data yang berasal dari web service tersebut.

  3. Membuat http request ke web service menggunakan dependency http.

  4. Mengkonversikan objek yang didapatkan dari web service ke model yang telah kita buat di langkah kedua.

  5. Menampilkan data yang telah dikonversi ke aplikasi dengan FutureBuilder.

Selengkapnya dapat dibaca pada tautan berikut: https://docs.flutter.dev/cookbook/networking/fetch-data#5-display-the-data

Tutorial: Refactor File

Refaktorisasi kode (refactor code) adalah proses restrukturisasi kode program yang ada tanpa mengubah behavior program. Proses ini dilakukan untuk meningkatkan keterbacaan, mengurangi kompleksitas kode, dan memudahkan proses maintenance ke depannya.

  1. Buka proyek yang sebelumnya telah dibuat pada tutorial sebelumnya dengan menggunakan IDE favoritmu.

  2. Di dalam folder lib, buatlah dua folder baru dengan nama model dan page.

  3. Pindahkan file selain main.dart ke dalam ke folder page.

Tutorial: Membuat Model Kustom

Dalam membuat model yang menyesuaikan dengan data JSON, kita dapat memanfaatkan website Quicktype dengan tahapan sebagai berikut.

  1. Buka situs web https://jsonplaceholder.typicode.com/todos?_start=0&_limit=10 untuk mendapatkan data JSON.

  2. Salinlah data JSON pada situs web sebelumnya, kemudian buka situs web Quicktype.

  3. Pada situs web Quicktype, ubahlah setup name menjadi ToDo, source type menjadi JSON, dan language menjadi Dart.

  4. Tempel data JSON yang telah disalin sebelumnya ke dalam textbox yang tersedia pada Quicktype.

    Berikut adalah contoh hasilnya.

    Quicktype Example

  5. Klik pilihan Copy Code pada Quicktype.

Setelah mendapatkan kode model melalui Quicktype, buka kembali proyek Flutter dan lakukan langkah-langkah berikut.

  1. Buatlah file baru pada folder lib/model dengan nama to_do.dart.

  2. Tempel kode yang telah disalin sebelumnya ke file to_do.dart.

Catatan: Jika kamu mengalami error saat membuat model, tambahkan keyword required pada setiap parameter model pada bagian constructor.

Tutorial: Menambahkan Dependensi HTTP

Untuk melakukan perintah HTTP request, kita membutuhkan package tambahan yakni package http.

  1. Lakukan flutter pub add http pada terminal proyek Flutter untuk menambahkan package http.

  2. Pada file android/app/src/main/AndroidManifest.xml, tambahkan kode berikut untuk memperbolehkan akses Internet pada aplikasi Flutter yang sedang dibuat.

    ...
    <application>
    ...
    </application>
    <!-- Required to fetch data from the Internet. -->
    <uses-permission android:name="android.permission.INTERNET" />
    ...

Tutorial: Mengambil dan Mengolah Data dari Web Service

  1. Buatlah file baru pada folder lib/page dengan nama to_do_page.dart.

  2. Pada file to_do_page.dart, tambahkan impor yang dibutuhkan. Ubahlah <APP_NAME> sesuai dengan nama proyek Flutter yang kalian buat.

    import 'package:http/http.dart' as http;
    import 'dart:convert';
    import 'package:<APP_NAME>/model/to_do.dart';
    ...
  3. Buatlah stateful widget dengan nama class ToDoPage. Contoh struktur stateful widget dapat dilihat pada tautan berikut.

  4. Lakukan pengambilan data dari URL https://jsonplaceholder.typicode.com/todos?_start=0&_limit=10 menggunakan metode http.get.

    class ToDoPage extends StatefulWidget {
    const ToDoPage({Key? key}) : super(key: key);

    @override
    _ToDoPageState createState() => _ToDoPageState();
    }

    class _ToDoPageState extends State<ToDoPage> {
    Future<List<ToDo>> fetchToDo() async {
    var url = Uri.parse('https://jsonplaceholder.typicode.com/todos?_start=0&_limit=10');
    var response = await http.get(
    url,
    headers: {
    "Access-Control-Allow-Origin": "*",
    "Content-Type": "application/json",
    },
    );

    // melakukan decode response menjadi bentuk json
    var data = jsonDecode(utf8.decode(response.bodyBytes));

    // melakukan konversi data json menjadi object ToDo
    List<ToDo> listToDo = [];
    for (var d in data) {
    if (d != null) {
    listToDo.add(ToDo.fromJson(d));
    }
    }

    return listToDo;
    }
    ...
    }

Tutorial: Menampilkan Data dari Web Service

  1. Pada file main.dart dan form.dart tambahkan kode berikut untuk menambahkan menu To Do pada drawer yang telah kita buat (letakkan di bawah menu ListTile form).

    ListTile(
    title: const Text('To Do'),
    onTap: () {
    // Route menu ke halaman to do
    Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => const ToDoPage()),
    );
    },
    ),

    Sehingga kodenya menjadi seperti ini:

    ...
    ListTile(
    title: const Text('Form'),
    onTap: () {
    // Route menu ke halaman form
    Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => const MyFormPage()),
    );
    },
    ),
    ListTile(
    title: const Text('To Do'),
    onTap: () {
    // Route menu ke halaman to do
    Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => const ToDoPage()),
    );
    },
    ),
    ...
  2. Pada bagian Widget(BuildContext context), tambahkan kode berikut setelah return.

    Scaffold(
    appBar: AppBar(
    title: const Text('To Do'),
    ),
    drawer: Drawer(
    child: Column(
    children: [
    // Menambahkan clickable menu
    ListTile(
    title: const Text('Counter'),
    onTap: () {
    // Route menu ke halaman utama
    Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => const MyApp()),
    );
    },
    ),
    ListTile(
    title: const Text('Form'),
    onTap: () {
    // Route menu ke halaman form
    Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => const MyFormPage()),
    );
    },
    ),
    ListTile(
    title: const Text('ToDo'),
    onTap: () {
    // Route menu ke halaman to do
    Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => const ToDoPage()),
    );
    },
    ),
    ],
    ),
    ),
    body: FutureBuilder(
    future: fetchToDo(),
    builder: (context, AsyncSnapshot snapshot) {
    if (snapshot.data == null) {
    return const Center(child: CircularProgressIndicator());
    } else {
    if (!snapshot.hasData) {
    return Column(
    children: const [
    Text(
    "Tidak ada to do list :(",
    style: TextStyle(
    color: Color(0xff59A5D8),
    fontSize: 20),
    ),
    SizedBox(height: 8),
    ],
    );
    } else {
    return ListView.builder(
    itemCount: snapshot.data!.length,
    itemBuilder: (_, index)=> Container(
    margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
    padding: const EdgeInsets.all(20.0),
    decoration: BoxDecoration(
    color:Colors.white,
    borderRadius: BorderRadius.circular(15.0),
    boxShadow: const [
    BoxShadow(
    color: Colors.black,
    blurRadius: 2.0
    )
    ]
    ),
    child: Column(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    Text(
    "${snapshot.data![index].title}",
    style: const TextStyle(
    fontSize: 18.0,
    fontWeight: FontWeight.bold,
    ),
    ),
    const SizedBox(height: 10),
    Text("${snapshot.data![index].completed}"),
    ],
    ),
    )
    );
    }
    }
    }
    )
    );
  3. Restart aplikasi dengan menekan tombol r pada command line atau terminal di tempat kamu menjalankan Flutter. Hasilnya akan seperti gambar di bawah.

    Example App

Akhir Kata

Selamat, kamu telah mempelajari mengenai model dan web service pada Flutter!

Jika kamu ingin mencoba tantangan, maka cobalah untuk menerapkan hal berikut pada tutorial ini.

  • Lakukan refactor pada method fetchToDo ke file terpisah.

Referensi Tambahan

Kontributor

  • Zuhal 'Alimul Hadi
  • Sabyna Maharani
  • Brandon Ivander
  • Muhammad Athallah