Back to IF3210 Pengembangan Aplikasi Piranti Bergerak

Retrofit and Repository Pattern for Network Requests

Questions/Cues

  • Apa perbedaan antara HttpsURLConnection, Retrofit, dan Volley?
  • Bagaimana Retrofit mengubah HTTP API menjadi interface Kotlin?
  • Apa peran Moshi dalam alur permintaan jaringan?
  • Mengapa Repository pattern penting sebagai abstraksi sumber data?
  • Bagaimana ViewModel dan SavedStateHandle membantu menangani perubahan konfigurasi?

Reference Points

  • IF3210 Pengembangan Aplikasi Piranti Bergerak (Slides 9-15)

Pilihan HTTP Client di Android

Android menyediakan beberapa opsi untuk melakukan HTTP request, masing-masing dengan kelebihan dan kasus penggunaan yang berbeda:

  • HttpsURLConnection — klien HTTP bawaan Android yang mendukung TLS/SSL. Tidak memerlukan dependensi tambahan, tetapi penulisan kodenya lebih verbose dan membutuhkan penanganan koneksi, stream, dan parsing secara manual
  • Retrofit — library jaringan yang mengubah HTTP API menjadi interface Kotlin. Dibangun di atas OkHttp yang mendukung HTTP/2, connection pooling, dan response caching. Sangat direkomendasikan untuk aplikasi yang berinteraksi dengan REST API
  • Volley — library yang dikembangkan Google, cocok untuk request HTTP sederhana dan pengunduhan gambar, tetapi kurang fleksibel dibanding Retrofit untuk use case modern

Retrofit: HTTP API sebagai Interface Kotlin

Retrofit mengabstraksikan kompleksitas HTTP dengan cara yang elegan: developer mendefinisikan endpoint API sebagai interface Kotlin, dan Retrofit secara otomatis menghasilkan implementasinya saat runtime.

Dependensi Gradle yang dibutuhkan:

// build.gradle.kts
dependencies {
    implementation("com.squareup.retrofit2:retrofit:2.x.x")
    implementation("com.squareup.retrofit2:converter-moshi:2.x.x")
    implementation("com.squareup.moshi:moshi:1.x.x")
    implementation("com.squareup.moshi:moshi-kotlin:1.x.x")
}

Contoh definisi service interface dengan Retrofit:

interface UserService {
    @GET("users/{id}")
    suspend fun getUser(@Path("id") userId: Int): User
}

Inisialisasi instance Retrofit dilakukan sekali dan digunakan ulang:

val retrofit = Retrofit.Builder()
    .baseUrl("https://api.example.com/")
    .addConverterFactory(MoshiConverterFactory.create())
    .build()
 
val userService = retrofit.create(UserService::class.java)

Retrofit dibangun di atas OkHttp yang menyediakan fitur-fitur penting: dukungan HTTP/2 (multiplexing koneksi), connection pooling (penggunaan ulang koneksi TCP), dan response caching (menghindari request duplikat yang tidak perlu).

Moshi: Parsing JSON ke Objek Kotlin

Moshi adalah library JSON modern dari Square yang dirancang khusus untuk Kotlin. Perannya dalam alur jaringan adalah mengkonversi JSON yang diterima dari server menjadi objek data Kotlin (dan sebaliknya).

Untuk integrasi dengan Kotlin, Moshi menggunakan KotlinJsonAdapterFactory agar dapat memproses fitur bahasa Kotlin seperti parameter default dan nullability secara tepat:

private val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

Data class yang akan di-parse harus dianotasi dengan @JsonClass:

@JsonClass(generateAdapter = true)
data class User(
    val id: Int,
    val name: String,
    val email: String
)

Moshi dikonfigurasi sebagai ConverterFactory saat membangun instance Retrofit, sehingga konversi JSON-ke-objek terjadi secara otomatis.

Repository Design Pattern

Repository pattern adalah pola arsitektur yang menempatkan sebuah kelas sebagai satu-satunya sumber kebenaran (single source of truth) untuk data tertentu. Repository bertanggung jawab untuk:

  • Mengorkestrasi operasi data dari berbagai sumber (jaringan, database lokal, cache)
  • Menyembunyikan detail implementasi pengambilan data dari lapisan UI dan ViewModel
  • Menyediakan API yang bersih sehingga ViewModel tidak perlu tahu apakah data berasal dari jaringan atau cache lokal
class UserRepository(private val userService: UserService) {
    suspend fun getUser(id: Int): User {
        return userService.getUser(id)
    }
}

Alur Data End-to-End

Berikut alur lengkap dari permintaan data pengguna hingga ditampilkan di UI:

flowchart TD
    A["App UI</br>(Fragment/Activity)"] -->|"observe LiveData"| B["ViewModel"]
    B -->|"memanggil"| C["Repository"]
    C -->|"HTTP Request"| D["Retrofit</br>Service"]
    D -->|"via OkHttp"| E["Server</br>(REST API)"]
    E -->|"HTTP Response</br>(JSON)"| D
    D -->|"MoshiConverter</br>parsing"| C
    C -->|"objek Kotlin"| B
    B -->|"update LiveData"| A

Setiap lapisan memiliki tanggung jawab yang jelas: UI hanya mengamati dan menampilkan data; ViewModel mengelola state dan logika bisnis presentasi; Repository mengorkestrasi sumber data; Retrofit menangani komunikasi HTTP; Moshi menangani serialisasi/deserialisasi JSON.

Mempertahankan Data Saat Perubahan Konfigurasi

Perubahan konfigurasi seperti rotasi layar akan menghancurkan dan membuat ulang Activity/Fragment. Untuk mempertahankan data yang sudah di-fetch dari jaringan, gunakan ViewModel yang bertahan selama siklus hidup Activity. Untuk mempertahankan state input pengguna yang sederhana (misalnya ID yang sedang dilihat), gunakan SavedStateHandle di dalam ViewModel:

class UserViewModel(
    private val savedStateHandle: SavedStateHandle,
    private val repository: UserRepository
) : ViewModel() {
    val userId = savedStateHandle.getStateFlow("userId", 0)
}

Summary

Android menyediakan tiga opsi HTTP client utama: HttpsURLConnection (bawaan), Retrofit (antarmuka berbasis interface, direkomendasikan), dan Volley (untuk use case sederhana). Retrofit mengubah HTTP API menjadi interface Kotlin dengan anotasi seperti @GET, dibangun di atas OkHttp dengan dukungan HTTP/2 dan connection pooling. Moshi menangani konversi JSON ke objek Kotlin secara otomatis sebagai ConverterFactory. Repository pattern mengabstraksikan sumber data sehingga ViewModel mendapat API yang bersih tanpa perlu tahu detail implementasi. Seluruh alur data mengalir: UI → ViewModel → Repository → Retrofit → Server, lalu kembali melalui Moshi. SavedStateHandle menjaga state penting tetap ada saat terjadi perubahan konfigurasi.