Rest API - News App
Nama : Rafaela Shyra Ashma' Ramadhani
NRP : 5025231217
Kelas : Pemrograman Perangkat Bergerak - B
Tugas Rest API - News App
Hasil Aplikasi:
Source Code: GitHub
Penjelasan:
Konsep Dasar
Aplikasi ini mengimplementasikan konsep REST API yang dijelaskan di materi dosen. REST API adalah standar komunikasi antara client (Android App) dan server menggunakan protokol HTTP. Dalam alur kerjanya, aplikasi Android mengirim HTTP Request ke server, lalu server mengembalikan data dalam format JSON yang kemudian ditampilkan ke layar pengguna. Project News App ini mengonsumsi data dari NewsAPI.org menggunakan arsitektur MVVM, Retrofit, Kotlin Coroutines, StateFlow, dan Jetpack Compose.
Model Data — News.kt
File ini mendefinisikan struktur data yang merepresentasikan response JSON dari NewsAPI. Ada tiga data class di sini:
NewsResponse, Article, dan Source. NewsResponse adalah struktur paling luar yang berisi status, totalResults, dan list artikel — persis seperti struktur JSON yang ditunjukkan di materi dosen. Article merepresentasikan satu berita dengan properti seperti title, author, urlToImage, publishedAt, dan content. Setiap properti diberi anotasi @SerializedName dari Gson — anotasi ini berfungsi untuk mapping nama field di JSON ke nama properti di Kotlin, misalnya @SerializedName("urlToImage") memberitahu Gson bahwa field bernama "urlToImage" di JSON harus dimasukkan ke properti urlToImage di data class. Semua properti dibuat nullable (menggunakan ?) karena tidak semua field dijamin selalu ada di setiap response dari API.API Service — ApiService.kt
File ini adalah interface Retrofit yang mendefinisikan endpoint-endpoint API yang akan digunakan. Sesuai materi dosen, ada tiga fungsi di sini:
getTopHeadlines untuk mengambil berita utama lewat endpoint GET /v2/top-headlines, searchNews untuk mencari berita berdasarkan kata kunci lewat endpoint GET /v2/everything, dan getNewsByCategory untuk mengambil berita berdasarkan kategori tertentu juga lewat endpoint GET /v2/top-headlines namun dengan tambahan parameter category. Anotasi @GET memberitahu Retrofit bahwa fungsi ini melakukan HTTP GET request ke path yang ditentukan. Parameter seperti country, apiKey, q, dan category ditambahkan sebagai query parameter menggunakan anotasi @Query, sehingga Retrofit secara otomatis menyusun URL lengkap seperti https://newsapi.org/v2/top-headlines?country=us&apiKey=xxx. Semua fungsi menggunakan kata kunci suspend karena dipanggil dari dalam coroutine agar tidak membekukan tampilan aplikasi.Retrofit Instance — RetrofitInstance.kt
File ini adalah konfigurasi Retrofit yang dibuat menggunakan pola Singleton dengan
object. Pola Singleton memastikan hanya ada satu instance Retrofit yang dibuat selama aplikasi berjalan, sehingga tidak boros memori. BASE_URL diset ke https://newsapi.org/ sesuai dokumentasi NewsAPI. Di dalamnya juga dikonfigurasi OkHttpClient dengan HttpLoggingInterceptor yang berguna untuk melihat detail HTTP request dan response di Logcat saat proses debugging — sangat berguna untuk memastikan request yang dikirim sudah benar. Timeout juga diatur ke 30 detik untuk connect, read, dan write agar aplikasi tidak menunggu terlalu lama saat koneksi buruk. GsonConverterFactory ditambahkan agar Retrofit otomatis mengubah JSON response menjadi data class Kotlin tanpa perlu parsing manual. Instance api dibuat menggunakan by lazy, artinya Retrofit baru dibuat saat pertama kali diakses, bukan saat aplikasi pertama dibuka.Repository — NewsRepository.kt
Repository berperan sebagai single source of truth untuk data, menjadi lapisan perantara antara ViewModel dan sumber data (API). Di sini terdapat sealed class
NewsResult yang merepresentasikan tiga kemungkinan kondisi: Success ketika data berhasil diambil, Error ketika terjadi kesalahan, dan Loading saat proses pengambilan data berlangsung. Ada dua fungsi utama di sini: getTopHeadlines() untuk mengambil berita terkini, dan searchNews() untuk mencari berita. Keduanya menggunakan blok try-catch untuk menangani error jaringan secara aman. Ketika response berhasil (response.isSuccessful), artikel difilter terlebih dahulu untuk menghapus artikel dengan judul null atau bertuliskan "[Removed]" yang kadang muncul di response NewsAPI. Jika request gagal, pesan error dikembalikan beserta kode HTTP dari server untuk memudahkan debugging.ViewModel — NewsViewModel.kt
ViewModel bertugas sebagai jembatan antara data dari Repository dan tampilan UI. Di sini terdapat sealed class
NewsUiState dengan empat kondisi: Idle (belum ada aksi), Loading (sedang memuat), Success (data berhasil), dan Error (terjadi kesalahan). Setiap state ini menentukan apa yang ditampilkan di layar. Data disimpan dan dialirkan menggunakan MutableStateFlow yang dibungkus menjadi StateFlow lewat .asStateFlow() sebelum diekspos ke UI — ini agar UI hanya bisa membaca state, bukan mengubahnya secara langsung. Ada lima StateFlow terpisah: homeNewsState untuk berita utama, searchNewsState untuk hasil pencarian, savedArticles untuk artikel tersimpan, searchQuery untuk teks pencarian, dan selectedArticle untuk artikel yang sedang dibuka di DetailScreen. Fungsi fetchTopHeadlines() dan searchNews() dijalankan di dalam viewModelScope.launch — coroutine scope yang otomatis dibatalkan ketika ViewModel dihancurkan, sehingga aman dari memory leak. Blok init {} memastikan berita langsung diambil begitu ViewModel pertama kali dibuat.HomeScreen.kt
HomeScreen adalah layar utama yang menampilkan daftar berita terkini. State dari ViewModel diamati menggunakan
collectAsStateWithLifecycle() — fungsi ini lebih efisien karena secara otomatis berhenti mengamati ketika UI tidak aktif (lifecycle-aware), sehingga tidak ada proses yang berjalan sia-sia di background. Layar ini menggunakan when expression untuk menangani setiap kondisi NewsUiState: jika Loading tampilkan CircularProgressIndicator, jika Success tampilkan daftar berita menggunakan LazyColumn, jika Error tampilkan pesan error beserta tombol Coba Lagi, dan jika Idle panggil fetchTopHeadlines() lewat LaunchedEffect. Pull-to-refresh diimplementasikan menggunakan rememberPullRefreshState di mana ketika pengguna menarik layar ke bawah, fungsi viewModel.fetchTopHeadlines() dipanggil kembali. Artikel pertama ditampilkan sebagai FeaturedNewsCard berukuran besar, sedangkan artikel berikutnya menggunakan articles.drop(1) untuk mengambil sisa artikel yang ditampilkan sebagai NewsCard dalam bentuk list.DetailScreen.kt
DetailScreen menampilkan isi lengkap sebuah artikel yang dipilih pengguna. Artikel yang ditampilkan diambil dari
viewModel.selectedArticle yang sebelumnya di-set ketika pengguna mengetuk kartu berita di layar lain. Jika selectedArticle bernilai null, layar menampilkan pesan "Artikel tidak ditemukan" sebagai fallback. Di TopAppBar terdapat dua tombol aksi: tombol OpenInBrowser untuk membuka URL artikel di browser menggunakan Intent.ACTION_VIEW, dan tombol bookmark yang menampilkan ikon Bookmark atau BookmarkBorder tergantung apakah artikel sudah disimpan atau belum. Konten artikel dari NewsAPI biasanya terpotong dan diakhiri dengan "[+xxxx chars]", sehingga dilakukan pembersihan menggunakan content.replace(Regex("""\[\+\d+ chars\]"""), "...") sebelum ditampilkan agar lebih rapi.SearchScreen.kt
SearchScreen mengimplementasikan fitur pencarian menggunakan endpoint
GET /v2/everything dari NewsAPI sesuai contoh di materi dosen. Terdapat OutlinedTextField untuk input kata kunci dengan tombol clear (ikon X) yang hanya muncul ketika field tidak kosong, serta konfigurasi KeyboardOptions(imeAction = ImeAction.Search) agar tombol search muncul di keyboard virtual. Pencarian baru dijalankan ketika pengguna menekan tombol Cari atau tombol search di keyboard lewat KeyboardActions(onSearch = {...}) — bukan setiap ketikan, agar tidak terlalu banyak memanggil API. Setelah pencarian selesai, focusManager.clearFocus() dipanggil untuk menyembunyikan keyboard otomatis. Seperti HomeScreen, hasil pencarian juga menangani empat kondisi state: Idle (belum pernah mencari, tampilkan ilustrasi), Loading, Success (tampilkan list hasil), dan Error.SavedScreen.kt & NewsCard.kt
SavedScreen menampilkan artikel-artikel yang telah disimpan pengguna menggunakan fitur bookmark. Data diambil dari
viewModel.savedArticles yang berupa StateFlow<List<Article>>, sehingga tampilan otomatis terupdate setiap kali ada artikel yang ditambah atau dihapus tanpa perlu reload manual. Ketika belum ada artikel tersimpan, ditampilkan empty state dengan emoji 🔖 dan pesan panduan. NewsCard.kt adalah komponen reusable yang dipakai bersama di HomeScreen, SearchScreen, dan SavedScreen. Ada dua varian fungsi composable: FeaturedNewsCard untuk tampilan besar dengan overlay gambar gelap di atasnya menggunakan Canvas untuk efek transparansi, dan NewsCard untuk tampilan list kecil dengan gambar thumbnail di kiri dan teks di kanan. Kedua komponen menerima parameter isSaved dan onSaveClick untuk mengontrol tampilan dan aksi tombol bookmark, serta menggunakan AsyncImage dari library Coil untuk memuat gambar dari URL secara asinkron.DateUtils.kt
File ini berisi satu fungsi helper
formatDate() yang mengubah format tanggal dari string ISO 8601 (seperti 2024-01-15T10:30:00Z yang dikirim NewsAPI) menjadi format yang lebih mudah dibaca manusia. Fungsi ini menggunakan SimpleDateFormat untuk melakukan parsing, lalu menghitung selisih waktu antara tanggal artikel dengan waktu sekarang menggunakan Date(). Hasilnya ditampilkan secara relatif: jika kurang dari 60 menit ditampilkan "X menit yang lalu", jika kurang dari 24 jam ditampilkan "X jam yang lalu", jika kurang dari 7 hari ditampilkan "X hari yang lalu", dan jika lebih dari itu ditampilkan format tanggal lengkap dalam bahasa Indonesia menggunakan Locale("id", "ID"). Seluruh proses dibungkus dalam try-catch sehingga jika format tanggal dari API tidak sesuai ekspektasi, fungsi cukup mengembalikan string aslinya tanpa crash.MainActivity.kt
MainActivity adalah entry point aplikasi dan pusat konfigurasi navigasi. Di sini digunakan Navigation Compose dengan
rememberNavController() untuk mengatur perpindahan antar layar. Terdapat empat rute navigasi yang didefinisikan di object NewsRoutes: home, search, saved, dan detail. Bottom Navigation Bar ditampilkan di tiga halaman utama dan disembunyikan otomatis di DetailScreen menggunakan kondisi showBottomBar = currentRoute != NewsRoutes.DETAIL. Title di TopAppBar juga berubah dinamis menggunakan when (currentRoute) sesuai halaman yang aktif. ViewModel dibuat satu kali di sini menggunakan viewModel() lalu diteruskan sebagai parameter ke semua screen — ini disengaja agar semua screen berbagi instance ViewModel yang sama, sehingga state seperti selectedArticle yang di-set di HomeScreen bisa langsung dibaca oleh DetailScreen tanpa perlu dikirim lewat argumen navigasi.Kesimpulan
Melalui project News App ini, saya memahami secara langsung bagaimana REST API bekerja di dalam aplikasi Android. Konsep yang dijelaskan di materi dosen — mulai dari HTTP Request, JSON Response, hingga cara menampilkan data ke layar — semuanya terimplementasi di project ini. Retrofit menyederhanakan proses komunikasi dengan API sehingga kita tidak perlu menulis HTTP request secara manual. Kotlin Coroutines memastikan proses pengambilan data berjalan di background tanpa membekukan tampilan. StateFlow membuat UI selalu sinkron dengan data terbaru dari ViewModel secara otomatis. Arsitektur MVVM memisahkan tanggung jawab setiap bagian kode dengan jelas — Model mengurus struktur data, Repository mengurus pengambilan data, ViewModel mengurus logika dan state, sementara View hanya bertugas menampilkan. Kombinasi semua teknologi ini menghasilkan aplikasi yang bersih, terstruktur, dan mudah dikembangkan lebih lanjut.




Komentar
Posting Komentar