Overview #
Hampir setiap aplikasi mobile modern berkomunikasi dengan server — mengambil data, mengirim formulir, memproses pembayaran, atau menerima notifikasi. Di Flutter, semua komunikasi jaringan dibangun di atas protokol HTTP/HTTPS dan ekosistem package yang kaya. Sebelum membahas implementasi spesifik, penting memahami fondasi: bagaimana HTTP bekerja, apa saja komponen request dan response, dan bagaimana Flutter mengarsitektur layer networking yang bersih.
Bagaimana HTTP Bekerja #
HTTP (HyperText Transfer Protocol) adalah protokol komunikasi antara client (aplikasi Flutter) dan server (backend API). Setiap interaksi mengikuti pola yang sama: client mengirim request, server memproses, dan mengembalikan response.
Flutter App (Client) Server (API Backend)
│ │
│──── HTTP Request ──────────────────→ │
│ Method: GET │ Proses request
│ URL: /api/produk │ Query database
│ Headers: Authorization: Bearer... │ Format response
│ Body: (opsional) │
│ │
│ ←─── HTTP Response ─────────────── │
│ Status: 200 OK │
│ Headers: Content-Type: app/json │
│ Body: [{"id":1,"nama":"..."}] │
│ │
HTTP Methods #
Setiap request menggunakan method yang menunjukkan operasi yang ingin dilakukan:
GET -- Ambil data (read-only, tidak ada body request)
Contoh: GET /api/produk → daftar produk
Contoh: GET /api/produk/123 → produk dengan ID 123
POST -- Buat data baru (body berisi data yang akan dibuat)
Contoh: POST /api/produk → tambah produk baru
Contoh: POST /api/auth/login → login
PUT -- Update seluruh data (replace)
Contoh: PUT /api/produk/123 → update semua field produk 123
PATCH -- Update sebagian data
Contoh: PATCH /api/produk/123 → update hanya field tertentu
DELETE -- Hapus data
Contoh: DELETE /api/produk/123 → hapus produk 123
Status Code #
Server merespons dengan status code tiga digit yang menunjukkan hasil request:
2xx -- SUKSES
200 OK -- Request berhasil (GET, PUT, PATCH)
201 Created -- Data berhasil dibuat (POST)
204 No Content -- Berhasil tapi tidak ada body (DELETE)
3xx -- REDIRECT
301 Moved Permanently -- URL telah berpindah permanen
304 Not Modified -- Data tidak berubah (dari cache)
4xx -- ERROR CLIENT (kesalahan dari sisi kita)
400 Bad Request -- Request tidak valid (format salah, data kurang)
401 Unauthorized -- Belum login / token tidak valid
403 Forbidden -- Login tapi tidak punya izin
404 Not Found -- Resource tidak ditemukan
422 Unprocessable -- Data gagal validasi di server
5xx -- ERROR SERVER (kesalahan di sisi server)
500 Internal Server Error -- Error tak terduga di server
502 Bad Gateway -- Server upstream bermasalah
503 Service Unavailable -- Server sedang down / overload
Headers #
Headers adalah metadata yang dikirim bersama request atau response:
// Headers request yang umum
{
'Content-Type': 'application/json', // format body yang kita kirim
'Accept': 'application/json', // format response yang kita minta
'Authorization': 'Bearer eyJhbG...', // token autentikasi
'Accept-Language': 'id-ID', // bahasa yang diinginkan
'X-Request-ID': 'uuid-unik', // ID untuk tracking/debugging
}
// Headers response yang umum
{
'Content-Type': 'application/json', // format body yang dikembalikan
'Content-Length': '1234', // ukuran body dalam bytes
'Cache-Control': 'max-age=3600', // instruksi caching
'X-RateLimit-Remaining': '95', // sisa quota request
}
JSON — Format Data Universal #
JSON (JavaScript Object Notation) adalah format pertukaran data yang paling umum digunakan di REST API. Di Flutter, JSON dikonversi ke-dan-dari Dart objects:
// JSON dari server
{
"id": 123,
"nama": "Flutter Book",
"harga": 150000.0,
"tersedia": true,
"kategori": ["buku", "programming"],
"penerbit": {
"nama": "Tech Publisher",
"kota": "Jakarta"
}
}
// Decode JSON dari String ke Map
import 'dart:convert';
final Map<String, dynamic> data = jsonDecode(responseBody);
final String nama = data['nama']; // 'Flutter Book'
final double harga = data['harga']; // 150000.0
final List kategoris = data['kategori']; // ['buku', 'programming']
final String kotaPenerbit = data['penerbit']['kota']; // 'Jakarta'
// Encode Map ke JSON String
final String jsonString = jsonEncode({
'nama': 'Produk Baru',
'harga': 99000,
});
Arsitektur Layer Networking #
Networking yang bersih memisahkan tanggung jawab ke beberapa layer. Ini memudahkan testing, pemeliharaan, dan pergantian implementasi:
┌─────────────────────────────────────────────┐
│ UI Layer │
│ Widget → hanya tampilkan data, kirim aksi │
└───────────────────┬─────────────────────────┘
│ data models (Produk, User, dll)
┌───────────────────▼─────────────────────────┐
│ State Management Layer │
│ Notifier/Bloc → koordinasi loading & state │
└───────────────────┬─────────────────────────┘
│ domain objects
┌───────────────────▼─────────────────────────┐
│ Repository Layer │
│ Abstraksi sumber data → interface bersih │
│ ProdukRepository.getAll() → List<Produk> │
└───────────────────┬─────────────────────────┘
│ data transfer objects (DTO)
┌───────────────────▼─────────────────────────┐
│ Data Source Layer │
│ RemoteDataSource → HTTP calls dengan Dio │
│ LocalDataSource → cache dengan Hive/SQLite │
└───────────────────┬─────────────────────────┘
│ HTTP requests/responses
┌───────────────────▼─────────────────────────┐
│ Network Layer │
│ Dio/HTTP client → interceptors, timeout │
└─────────────────────────────────────────────┘
Keuntungan arsitektur berlapis ini sangat nyata saat pengembangan. Jika API backend berubah, kita hanya mengubah RemoteDataSource tanpa menyentuh UI atau logika bisnis. Jika ingin menambah cache offline, cukup tambah LocalDataSource di Repository.
Peta Ekosistem Package Networking Flutter #
HTTP CLIENT:
http -- package resmi Dart, sederhana dan ringan
cocok untuk kebutuhan dasar
dio -- powerful, interceptors, retry, cancel token
pilihan utama untuk produksi
SERIALISASI JSON:
dart:convert -- built-in, manual parsing
json_annotation + json_serializable -- code generation, aman
freezed -- immutable models + serialisasi + union types
GRAPHQL:
graphql_flutter -- Query/Mutation/Subscription widgets
ferry -- alternatif dengan type-safety lebih baik
STORAGE LOKAL (untuk cache):
shared_preferences -- key-value sederhana
hive -- NoSQL cepat, cocok untuk cache
sqflite -- SQL relasional
AUTH:
flutter_secure_storage -- simpan token secara aman
google_sign_in -- OAuth Google
sign_in_with_apple -- OAuth Apple
KONEKSI:
connectivity_plus -- deteksi status koneksi internet
REST vs GraphQL — Pilihan Arsitektur API #
REST (Representational State Transfer):
✓ Sederhana dan familiar
✓ Didukung oleh hampir semua backend framework
✓ Mudah di-cache oleh CDN
✓ Dokumentasi matang (OpenAPI/Swagger)
✗ Over-fetching: response sering berisi data yang tidak dibutuhkan
✗ Under-fetching: butuh beberapa request untuk satu tampilan
✗ Versioning API bisa kompleks
GraphQL:
✓ Client meminta data yang dibutuhkan saja (no over/under-fetching)
✓ Single endpoint untuk semua operasi
✓ Schema yang self-documenting
✓ Subscriptions real-time built-in
✗ Kompleksitas lebih tinggi di backend
✗ Caching lebih sulit
✗ Kurva belajar lebih curam
Pilih REST jika: tim familiar, backend sudah ada, kebutuhan standar
Pilih GraphQL jika: banyak tipe klien, data kompleks, butuh real-time
Ringkasan #
- HTTP adalah protokol request-response antara Flutter (client) dan server. Setiap request punya method (GET/POST/PUT/DELETE), URL, headers, dan opsional body.
- Status code menunjukkan hasil: 2xx sukses, 4xx error client, 5xx error server. Selalu handle status code, jangan hanya handle exception.
- JSON adalah format pertukaran data universal — gunakan
jsonDecode()danjsonEncode()daridart:convertuntuk konversi dasar.- Gunakan arsitektur berlapis: UI → State Management → Repository → Data Source → HTTP Client. Setiap layer punya satu tanggung jawab.
- Ekosistem Flutter punya banyak pilihan:
httpuntuk kebutuhan sederhana,Diountuk produksi (interceptors, retry, cancel),graphql_flutteruntuk GraphQL.- REST cocok untuk sebagian besar kebutuhan. GraphQL cocok untuk aplikasi dengan banyak tipe klien dan kebutuhan data yang kompleks.
← Sebelumnya: State Management Best Practice Berikutnya: Dio & HTTP →