httpapigetMenengah5 mnt baca

HTTP GET dengan package http

Ambil data dari REST API dan tampilkan di ListView.

Kenapa Perlu HTTP GET?

Bayangkan aplikasi warkopmu menampilkan daftar menu. Kalau menu di-hardcode di kode, setiap ganti harga kamu harus rilis update baru ke Play Store. Dengan HTTP GET, aplikasi mengambil data terbaru dari server setiap dibuka: menu, harga, stok, promo. Itulah kenapa hampir semua aplikasi produksi melakukan GET ke REST API.

Package http (dibuat oleh Dart team sendiri) adalah cara paling ringan dan standar untuk ini. Tidak ada setup rumit, tidak ada code generation, cuma satu dependency.

Setup

bash
flutter pub add http

Lalu import di file yang butuh:

dart
import 'package:http/http.dart' as http;
import 'dart:convert';

Contoh 1: GET Sederhana

dart
Future<List<Produk>> ambilProduk() async {
  final res = await http.get(
    Uri.parse('https://api.contoh.com/produk'),
  );

  if (res.statusCode == 200) {
    final jsonList = jsonDecode(res.body) as List;
    return jsonList
        .map((e) => Produk.fromJson(e as Map<String, dynamic>))
        .toList();
  } else {
    throw Exception('Gagal memuat: ${res.statusCode}');
  }
}

Selalu cek statusCode sebelum parsing. Server bisa mengembalikan 404 atau 500 dengan body HTML, dan jsonDecode akan crash kalau kamu tidak cek dulu.

Contoh 2: GET dengan Query Params, Header, dan Timeout

Contoh yang lebih realistis, lengkap dengan pencarian, pagination, dan proteksi timeout:

dart
Future<List<Produk>> cariProduk(String kataKunci, {int halaman = 1}) async {
  final uri = Uri.https('api.contoh.com', '/produk', {
    'q': kataKunci,
    'halaman': '$halaman',
    'limit': '20',
  });

  final res = await http
      .get(uri, headers: {'Accept': 'application/json'})
      .timeout(const Duration(seconds: 10));

  switch (res.statusCode) {
    case 200:
      final jsonList = jsonDecode(res.body) as List;
      return jsonList
          .map((e) => Produk.fromJson(e as Map<String, dynamic>))
          .toList();
    case 401:
      throw Exception('Sesi berakhir, silakan login ulang');
    case 404:
      throw Exception('Endpoint tidak ditemukan');
    default:
      throw Exception('Gagal memuat data (${res.statusCode})');
  }
}

Pakai Uri.https dengan map query parameter supaya spasi dan karakter spesial di-encode otomatis. Jangan rangkai URL pakai string interpolation mentah kalau parameternya datang dari input pengguna.

Menampilkan Hasil dengan FutureBuilder

dart
FutureBuilder<List<Produk>>(
  future: _futureProduk,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(child: CircularProgressIndicator());
    }
    if (snapshot.hasError) {
      return Center(child: Text('Error: ${snapshot.error}'));
    }
    final produk = snapshot.data ?? [];
    return ListView.builder(
      itemCount: produk.length,
      itemBuilder: (context, i) => ListTile(title: Text(produk[i].nama)),
    );
  },
)

Simpan future di initState (misal _futureProduk = cariProduk('kopi')). Jangan panggil fungsi GET langsung di dalam future: karena build bisa jalan berkali-kali dan request-mu ikut terkirim berkali-kali.

Edge Case yang Wajib Kamu Tahu

  1. Tanpa timeout, request bisa menggantung selamanya. Di jaringan jelek, http.get tidak punya batas waktu bawaan. Selalu pasang .timeout().
  2. Localhost di emulator Android bukan localhost. Pakai http://10.0.2.2:8000 untuk menjangkau server di komputermu. Di iOS simulator, localhost biasa tetap bisa.
  3. Android 9+ memblokir HTTP polos. Kalau API lokalmu masih http://, tambahkan android:usesCleartextTraffic="true" di manifest saat development, atau lebih baik pakai HTTPS sekalian.
  4. Parsing bisa gagal walau status 200. Struktur JSON server bisa berubah sewaktu-waktu. Bungkus fromJson dengan nilai default yang aman (as String? ?? '') seperti di modul model JSON.

Catatan teknis: Untuk API yang butuh login, tambahkan header Authorization: Bearer $token seperti di modul HTTP POST. Simpan base URL di satu file konstanta supaya gampang diganti antara development dan production.

Kapan JANGAN Pakai Pendekatan Ini

  • Jangan kirim data sensitif lewat query params. Password atau token di URL bisa tersimpan di log server dan history. Untuk mengirim data, pakai POST dengan body.
  • Jangan panggil GET di dalam build(). Setiap rebuild memicu request baru. Simpan future-nya atau pakai state management.
  • Kalau butuh fitur lanjutan (auto refresh token, retry otomatis, interceptor logging), package http terlalu polos. Saat itu tiba, pindah ke dio yang memang dirancang untuk itu.

Tantangan

GET ke JSONPlaceholder

Ambil data dari https://jsonplaceholder.typicode.com/posts, parse menjadi List, dan tampilkan 10 judul pertama dalam ListView via FutureBuilder.