Belajar Flutter - Networking & Data Handling
Episode 8 of 23

Belajar Flutter - Networking & Data Handling

Episode ini menghubungkan aplikasi kalian ke dunia luar: HTTP requests dengan package http atau dio, JSON deserialization dengan dart:convert dan json_serializable, async programming dengan Future dan Stream, serta loading states, error handling, dan retry yang layak untuk produksi.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Aplikasi yang berguna hampir selalu membaca dan mengirim data ke server. Episode 8 membuka pintu itu: kalian akan belajar melakukan request HTTP, mengurai JSON menjadi model Dart, memahami async programming dengan Future dan Stream, serta menangani loading, error, dan retry seperti aplikasi produksi. Mulai dengan instalasi package:

Menambahkan package http
flutter pub add http

flutter pub add http menambahkan package http ke pubspec.yaml dan langsung menjalankan pub get. Untuk kebutuhan yang lebih besar, package dio menawarkan interceptors, timeout, dan upload progress — akan kita bandingkan sebentar lagi.

HTTP Requests dengan http atau dio

GET Request Dasar

Dengan package http, request sederhana hanya beberapa baris:

HTTP GET dengan package http
import 'package:http/http.dart' as http;
 
final response = await http.get(
  Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
);
 
if (response.statusCode == 200) {
  print(response.body);
} else {
  throw Exception('Gagal: ${response.statusCode}');
}

await http.get(Uri.parse(...)) mengembalikan Response. Selalu periksa statusCode sebelum memproses body. Perhatikan bahwa URL selalu dibungkus Uri.parsehttp.get menerima Uri, bukan string mentah.

Kapan Memakai dio

dio menambahkan fitur di atas http: interceptors untuk logging, base options untuk URL dasar, dan penanganan timeout yang lebih rapi. Untuk aplikasi dengan banyak endpoint dan kebutuhan auth, dio menghemat banyak boilerplate:

Alternatif dengan dio
flutter pub add dio

JSON Deserialization

Dari String JSON ke Model

dart:convert mengurai JSON mentah, lalu kalian memetakannya ke model Dart:

Model dengan fromJson manual
class Post {
  const Post({required this.id, required this.title});
 
  final int id;
  final String title;
 
  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'] as int,
      title: json['title'] as String,
    );
  }
}

Post.fromJson(json) memetakan key JSON ke field model. Gunakan jsonDecode(response.body) untuk mengubah string menjadi Map sebelum memanggil fromJson.

json_serializable untuk Skala Besar

Menulis fromJson manual membosankan saat model banyak. Package json_serializable membangkitkannya dari anotasi:

Menambahkan codegen JSON
flutter pub add json_annotation
flutter pub add dev:build_runner dev:json_serializable

Jalankan codegen:

Menjalankan build runner
dart run build_runner build

dart run build_runner build membangkitkan file .g.dart yang berisi implementasi fromJson dan toJson dari anotasi @JsonSerializable().

Async Programming dengan Future dan Stream

Future untuk Satu Hasil

Future mewakili operasi yang menghasilkan satu nilai di kemudian hari. Kombinasi async dan await membuat kode asinkron terbaca seperti kode sinkron:

Fungsi async dengan Future
Future<Post> ambilPost(int id) async {
  final response = await http.get(
    Uri.parse('https://jsonplaceholder.typicode.com/posts/$id'),
  );
  final json = jsonDecode(response.body) as Map<String, dynamic>;
  return Post.fromJson(json);
}

Fungsi bertipe Future<Post> memberi tahu pemanggil bahwa hasilnya belum siap. await menunggu hasil tanpa memblokir UI — kunci kenyamanan pemrograman asinkron di Flutter.

Stream untuk Data Berkelanjutan

Stream mewakili aliran data yang terus menerus — misalnya notifikasi atau progress. Di UI, StreamBuilder merender ulang setiap kali stream mengirim data baru:

Mendengarkan stream di UI
StreamBuilder<int>(
  stream: streamKoneksi,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return Text('Ping: ${snapshot.data} ms');
    }
    return const Text('Menunggu data...');
  },
)

StreamBuilder memanggil builder ulang setiap kali streamKoneksi mengirim nilai baru. snapshot.hasData dan snapshot.data memberi akses ke nilai terakhir.

Loading States, Error Handling, dan Retry

FutureBuilder dengan Kondisi Lengkap

Gunakan FutureBuilder untuk menampilkan loading, error, dan data dalam satu widget:

FutureBuilder dengan tiga kondisi
FutureBuilder<Post>(
  future: ambilPost(1),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const CircularProgressIndicator();
    }
    if (snapshot.hasError) {
      return Text('Terjadi kesalahan: ${snapshot.error}');
    }
    return Text(snapshot.data!.title);
  },
)

ConnectionState.waiting menunjukkan proses sedang berjalan — tampilkan spinner. snapshot.hasError memegang penanganan error, dan snapshot.data dipakai setelah data siap.

Pola Retry yang Aman

Jangan menyerah pada satu kegagalan jaringan. Buat helper retry dengan batas percobaan:

Helper retry dengan batas
Future<T> cobaUlang<T>(Future<T> Function() aksi, {int maks = 3}) async {
  for (var i = 0; i < maks; i++) {
    try {
      return await aksi();
    } catch (e) {
      if (i == maks - 1) rethrow;
      await Future.delayed(Duration(milliseconds: 500 * (i + 1)));
    }
  }
  throw StateError('Tidak terjangkau');
}

cobaUlang memanggil aksi hingga sukses atau mencapai maks percobaan. Jeda Duration(milliseconds: 500 * (i + 1)) memberi waktu server pulih — tanpa denyut yang terlalu agresif.

Penutup

Inti yang harus dibawa pulang:

  • http untuk project kecil; dio untuk kebutuhan interceptor dan timeout.
  • Selalu periksa statusCode dan bungkus URL dengan Uri.parse.
  • Model dengan fromJson manual atau codegen json_serializable.
  • Future untuk satu hasil; Stream untuk data berkelanjutan.
  • FutureBuilder menangani loading, error, dan data dalam satu tempat.
  • Retry dengan batas percobaan dan jeda eksponensial.

Di episode 9 selanjutnya kita membahas persistent storage — local storage dengan shared_preferences dan file I/O, database lokal SQLite dengan sqflite dan Drift, caching strategies dan offline support, serta secure storage untuk menyimpan token dan secret. Data aplikasi kalian tidak lagi hilang saat aplikasi ditutup.

Belajar Flutter - Networking & Data Handling | Belajar Flutter