Codelab ini adalah bagian dari kursus Dasar-Dasar Android Kotlin. Anda akan mendapatkan manfaat maksimal dari kursus ini jika menyelesaikan codelab secara berurutan. Semua codelab kursus tercantum di halaman landing codelab Dasar-Dasar Android Kotlin.
Pengantar
Hampir semua aplikasi Android yang Anda buat akan perlu terhubung ke internet pada suatu saat. Dalam codelab ini dan codelab berikutnya, Anda akan membuat aplikasi yang terhubung ke layanan web untuk mengambil dan menampilkan data.  Anda juga akan membangun apa yang telah Anda pelajari di codelab sebelumnya tentang ViewModel, LiveData, dan RecyclerView. 
Dalam codelab ini, Anda menggunakan library yang dikembangkan komunitas untuk membuat lapisan jaringan. Hal ini sangat menyederhanakan pengambilan data dan gambar, serta membantu aplikasi agar sesuai dengan beberapa praktik terbaik Android, seperti memuat gambar di thread latar belakang dan menyimpan gambar yang dimuat dalam cache. Untuk bagian asinkron atau non-blocking dalam kode, seperti berkomunikasi dengan lapisan layanan web, Anda akan mengubah aplikasi untuk menggunakan coroutine Kotlin. Anda juga akan mengupdate antarmuka pengguna aplikasi jika internet lambat atau tidak tersedia untuk memberi tahu pengguna apa yang sedang terjadi.
Yang harus sudah Anda ketahui
- Cara membuat dan menggunakan fragmen.
 - Cara beralih antar-fragmen, dan menggunakan 
safeArgsuntuk meneruskan data antar-fragmen. - Cara menggunakan komponen arsitektur termasuk transformasi 
ViewModel,ViewModelProvider.Factory,LiveData, danLiveData. - Cara menggunakan coroutine untuk tugas yang berjalan lama.
 
Yang akan Anda pelajari
- Apa itu layanan web REST.
 - Menggunakan library Retrofit untuk terhubung ke layanan web REST di internet dan mendapatkan respons.
 - Menggunakan library Moshi untuk mengurai respons JSON ke dalam objek data.
 
Yang akan Anda lakukan
- Memodifikasi aplikasi awal untuk membuat permintaan API layanan web dan menangani respons.
 - Terapkan lapisan jaringan untuk aplikasi Anda menggunakan library Retrofit.
 - Uraikan respons JSON dari layanan web ke data aktif aplikasi Anda dengan library Moshi.
 - Gunakan dukungan Retrofit untuk coroutine agar menyederhanakan kode.
 
Dalam codelab ini (dan codelab berikutnya), Anda akan menggunakan aplikasi starter bernama MarsRealEstate, yang menampilkan properti yang dijual di Mars. Aplikasi ini terhubung ke layanan web untuk mengambil dan menampilkan data properti, termasuk detail seperti harga dan apakah properti tersedia untuk dijual atau disewakan. Gambar yang merepresentasikan setiap properti adalah foto kehidupan nyata dari Mars yang diambil dari penjelajah Mars NASA.

Versi aplikasi yang Anda buat di codelab ini tidak akan memiliki banyak flash visual: berfokus pada bagian lapisan jaringan dari aplikasi untuk terhubung ke internet dan mendownload data properti mentah menggunakan layanan web. Untuk memastikan bahwa data diambil dan diuraikan dengan benar, Anda hanya perlu mencetak jumlah properti di Mars dalam tampilan teks:

.
Arsitektur untuk aplikasi MarsRealEstate memiliki dua modul utama:
- Fragmen ringkasan, yang berisi petak gambar properti thumbnail, yang dibuat dengan 
RecyclerView. - Fragmen tampilan detail, yang berisi informasi tentang setiap properti.
 

Aplikasi memiliki ViewModel untuk setiap fragmen. Untuk codelab ini, Anda membuat lapisan untuk layanan jaringan, dan ViewModel berkomunikasi langsung dengan lapisan jaringan tersebut.  Hal ini mirip dengan yang Anda lakukan di codelab sebelumnya saat ViewModel berkomunikasi dengan database Room.
ViewModel ringkasan bertanggung jawab untuk membuat panggilan jaringan guna mendapatkan informasi properti Mars. Detail ViewModel menyimpan detail untuk satu bagian lahan di Mars yang ditampilkan dalam fragmen detail.  Untuk setiap ViewModel, Anda menggunakan LiveData dengan data binding yang memperhatikan siklus proses untuk mengupdate UI aplikasi saat data berubah.  
Anda menggunakan komponen Navigation untuk menavigasi antara dua fragmen, dan untuk meneruskan properti yang dipilih sebagai argumen.
Dalam tugas ini, Anda akan mendownload dan menjalankan aplikasi awal untuk MarsRealEstate serta memahami struktur project.
Langkah 1: Jelajahi fragmen dan navigasi
- Download aplikasi awal MarsRealEstate dan buka di Android Studio.
 - Periksa 
app/java/MainActivity.kt. Aplikasi menggunakan fragmen untuk kedua layar, sehingga satu-satunya tugas untuk aktivitas adalah memuat tata letak aktivitas. - Periksa 
app/res/layout/activity_main.xml. Tata letak aktivitas adalah host untuk dua fragmen, yang ditentukan dalam file navigasi. Tata letak ini membuat instanceNavHostFragmentdan pengontrol navigasi terkaitnya dengan resourcenav_graph. - Buka 
app/res/navigation/nav_graph.xml. Di sini Anda dapat melihat hubungan navigasi antara kedua fragmen. Grafik navigasiStartDestinationmengarah keoverviewFragment, sehingga fragmen ringkasan dibuat instance-nya saat aplikasi diluncurkan. 
Langkah 2: Jelajahi file sumber Kotlindan data binding
- Di panel Project, luaskan app > java. Perhatikan bahwa aplikasi MarsRealEstate memiliki tiga folder paket:  
detail,network, danoverview. Ini sesuai dengan tiga komponen utama aplikasi Anda: ringkasan dan fragmen detail, serta kode untuk lapisan jaringan.
   - Buka 
app/java/overview/OverviewFragment.kt.OverviewFragmentmelakukan inisialisasiOverviewViewModelsecara lambat, yang berartiOverviewViewModeldibuat saat pertama kali digunakan. - Periksa metode 
onCreateView(). Metode ini meng-inflate tata letakfragment_overviewmenggunakan data binding, menetapkan pemilik siklus proses binding ke dirinya sendiri (this), dan menetapkan variabelviewModeldalam objekbindingke pemilik tersebut. Karena kita telah menetapkan pemilik siklus proses, setiapLiveDatayang digunakan dalam data binding akan otomatis diamati jika ada perubahan, dan UI akan diupdate sebagaimana mestinya. - Buka 
app/java/overview/OverviewViewModel. Karena responsnya adalahLiveDatadan kita telah menetapkan siklus proses untuk variabel binding, setiap perubahannya akan memperbarui UI aplikasi. - Periksa blok 
init. SaatViewModeldibuat, metodegetMarsRealEstateProperties()akan dipanggil. - Periksa metode 
getMarsRealEstateProperties(). Di aplikasi awal ini, metode ini berisi respons placeholder. Tujuan codelab ini adalah memperbaruiLiveDatarespons dalamViewModelmenggunakan data nyata yang Anda dapatkan dari internet. - Buka 
app/res/layout/fragment_overview.xml. Tata letak ini adalah tata letak untuk fragmen ringkasan yang Anda kerjakan dalam codelab ini, dan mencakup data binding untuk model tampilan. Tata letak ini mengimporOverviewViewModel, lalu mengikat respons dariViewModelkeTextView. Di codelab berikutnya, Anda akan mengganti tampilan teks dengan petak gambar diRecyclerView. - Kompilasi dan jalankan aplikasi. Yang Anda lihat di aplikasi versi saat ini hanyalah respons awal—"Setel Respons Mars API di sini!"
 
 
Data real estate Mars disimpan di server web, sebagai layanan web REST. Layanan web yang menggunakan arsitektur REST dibuat menggunakan komponen dan protokol web standar.
Anda membuat permintaan ke layanan web dengan cara standar melalui URI. URL web yang dikenal sebenarnya adalah jenis URI, dan keduanya digunakan secara bergantian sepanjang kursus ini. Misalnya, dalam aplikasi untuk pelajaran ini, Anda akan mengambil semua data dari server berikut:
https://android-kotlin-fun-mars-server.appspot.com
Jika Anda mengetik URL berikut di browser, Anda akan mendapatkan daftar semua properti real estate yang tersedia di Mars.
https://android-kotlin-fun-mars-server.appspot.com/realestate
Respons dari layanan web biasanya diformat dalam JSON, format pertukaran untuk merepresentasikan data terstruktur. Anda akan mempelajari JSON lebih lanjut di tugas berikutnya, tetapi penjelasan singkatnya adalah bahwa objek JSON adalah kumpulan pasangan nilai-kunci, terkadang disebut kamus, peta hash, atau array asosiatif. Kumpulan objek JSON adalah array JSON, dan array ini adalah array yang Anda dapatkan kembali sebagai respons dari layanan web.
Untuk memasukkan data ini ke dalam aplikasi, aplikasi Anda harus membuat koneksi jaringan dan berkomunikasi dengan server tersebut, lalu menerima dan mengurai data respons ke dalam format yang dapat digunakan aplikasi. Dalam codelab ini, Anda menggunakan library klien REST yang disebut Retrofit untuk membuat koneksi ini.
Langkah 1: Tambahkan dependensi Retrofit ke Gradle
- Buka build.gradle (Module: app).
 - Di bagian 
dependencies, tambahkan baris berikut untuk library Retrofit: 
implementation "com.squareup.retrofit2:retrofit:$version_retrofit"
implementation "com.squareup.retrofit2:converter-scalars:$version_retrofit"
Perhatikan bahwa nomor versi ditentukan secara terpisah dalam file Gradle project. Dependensi pertama adalah untuk library Retrofit 2, dan dependensi kedua adalah untuk pengonversi skalar Retrofit.  Pengonversi ini memungkinkan Retrofit menampilkan hasil JSON sebagai String. Kedua library bekerja bersama.
- Klik Sync Now untuk mem-build ulang project dengan dependensi baru.
 
Langkah 2: Terapkan MarsApiService
Retrofit membuat API jaringan untuk aplikasi berdasarkan konten dari layanan web. Library ini mengambil data dari layanan web dan merutekannya melalui library pengonversi terpisah yang mengetahui cara mendekode data dan menampilkannya dalam bentuk objek yang berguna. Retrofit mencakup dukungan bawaan untuk format data web populer seperti XML dan JSON. Retrofit pada akhirnya membuat sebagian besar lapisan jaringan untuk Anda, termasuk detail penting seperti menjalankan permintaan pada thread latar belakang.
Class MarsApiService menyimpan lapisan jaringan untuk aplikasi; yaitu, ini adalah API yang akan digunakan ViewModel untuk berkomunikasi dengan layanan web.  Di sinilah Anda akan menerapkan API layanan Retrofit.  
- Buka 
app/java/network/MarsApiService.kt. Saat ini, file hanya berisi satu hal: konstanta untuk URL dasar layanan web. 
private const val BASE_URL = 
   "https://android-kotlin-fun-mars-server.appspot.com"- Tepat di bawah konstanta tersebut, gunakan builder Retrofit untuk membuat objek Retrofit.  Impor 
retrofit2.Retrofitdanretrofit2.converter.scalars.ScalarsConverterFactorybila diminta. 
private val retrofit = Retrofit.Builder()
   .addConverterFactory(ScalarsConverterFactory.create())
   .baseUrl(BASE_URL)
   .build()
Retrofit memerlukan setidaknya dua hal yang tersedia untuk membangun API layanan web: URI dasar untuk layanan web, dan factory pengonversi.  Pengonversi memberi tahu Retrofit apa yang harus dilakukan dengan data yang didapat kembali dari layanan web.  Dalam hal ini, Anda ingin Retrofit mengambil respons JSON dari layanan web, dan menampilkannya sebagai String.  Retrofit memiliki ScalarsConverter yang mendukung string dan jenis sederhana lainnya, jadi Anda memanggil addConverterFactory() pada builder dengan instance ScalarsConverterFactory.  Terakhir, Anda memanggil build() untuk membuat objek Retrofit.
- Tepat di bawah panggilan ke builder Retrofit, tentukan antarmuka yang menentukan cara Retrofit berkomunikasi dengan server web menggunakan permintaan HTTP.  Impor 
retrofit2.http.GETdanretrofit2.Callbila diminta. 
interface MarsApiService {
    @GET("realestate")
    fun getProperties():
            Call<String>
}Saat ini tujuannya adalah mendapatkan string respons JSON dari layanan web, dan Anda hanya memerlukan satu metode untuk melakukannya: getProperties().  Untuk memberi tahu Retrofit apa yang harus dilakukan metode ini, gunakan anotasi @GET dan tentukan jalur, atau endpoint, untuk metode layanan web tersebut.  Dalam hal ini, endpoint disebut realestate. Saat metode getProperties() dipanggil, Retrofit menambahkan endpoint realestate ke URL dasar (yang Anda tentukan dalam builder Retrofit), dan membuat objek Call. Objek Call tersebut digunakan untuk memulai permintaan.
- Di bawah antarmuka 
MarsApiService, tentukan objek publik yang disebutMarsApiuntuk menginisialisasi layanan Retrofit. 
object MarsApi {
    val retrofitService : MarsApiService by lazy { 
       retrofit.create(MarsApiService::class.java) }
}Metode Retrofit create() membuat layanan Retrofit itu sendiri dengan antarmuka MarsApiService.  Karena panggilan ini mahal, dan aplikasi hanya memerlukan satu instance layanan Retrofit, Anda mengekspos layanan ke seluruh aplikasi menggunakan objek publik yang disebut MarsApi, dan menginisialisasi layanan Retrofit di sana secara lambat. Setelah semua penyiapan selesai, setiap kali aplikasi Anda memanggil MarsApi.retrofitService,  aplikasi akan mendapatkan objek Retrofit singleton yang menerapkan MarsApiService.
Langkah 3: Panggil layanan web di OverviewViewModel
- Buka 
app/java/overview/OverviewViewModel.kt. Scroll ke bawah ke metodegetMarsRealEstateProperties(). 
private fun getMarsRealEstateProperties() {
   _response.value = "Set the Mars API Response here!"
}Di sinilah Anda akan memanggil layanan Retrofit dan menangani string JSON yang ditampilkan. Saat ini hanya ada string placeholder untuk respons.
- Hapus baris placeholder yang menetapkan respons ke "Set the Mars API Response here!"
 - Di dalam 
getMarsRealEstateProperties(), tambahkan kode yang ditunjukkan di bawah. Imporretrofit2.Callbackdancom.example.android.marsrealestate.network.MarsApibila diminta.
MetodeMarsApi.retrofitService.getProperties()menampilkan objekCall. Kemudian, Anda dapat memanggilenqueue()pada objek tersebut untuk memulai permintaan jaringan pada thread latar belakang. 
MarsApi.retrofitService.getProperties().enqueue( 
   object: Callback<String> {
})- Klik kata 
object, yang digarisbawahi dengan warna merah. Pilih Code > Implement methods. PilihonResponse()danonFailure()dari daftar.
Android Studio menambahkan kode dengan TODO di setiap metode: 
override fun onFailure(call: Call<String>, t: Throwable) {
       TODO("not implemented") 
}
override fun onResponse(call: Call<String>, 
   response: Response<String>) {
       TODO("not implemented") 
}- Di 
onFailure(), hapus TODO dan tetapkan_responseke pesan kegagalan, seperti yang ditunjukkan di bawah._responseadalah stringLiveDatayang menentukan apa yang ditampilkan di tampilan teks. Setiap status perlu memperbarui_responseLiveData.
CallbackonFailure()dipanggil saat respons layanan web gagal. Untuk respons ini, setel status_responseke"Failure: "yang digabungkan dengan pesan dari argumenThrowable. 
override fun onFailure(call: Call<String>, t: Throwable) {
   _response.value = "Failure: " + t.message
}- Di 
onResponse(), hapus TODO dan tetapkan_responseke isi respons. CallbackonResponse()dipanggil saat permintaan berhasil dan layanan web menampilkan respons. 
override fun onResponse(call: Call<String>, 
   response: Response<String>) {
      _response.value = response.body()
}Langkah 4: Tentukan izin internet
- Kompilasi dan jalankan aplikasi MarsRealEstate.  Perhatikan bahwa aplikasi segera ditutup dengan error. 
   - Klik tab Logcat di Android Studio dan catat error dalam log, yang diawali dengan baris seperti ini:
 
Process: com.example.android.marsrealestate, PID: 10646 java.lang.SecurityException: Permission denied (missing INTERNET permission?)
Pesan error memberi tahu Anda bahwa aplikasi Anda mungkin tidak memiliki izin INTERNET. Menghubungkan ke internet menimbulkan masalah keamanan, itulah sebabnya aplikasi tidak memiliki koneksi internet secara default. Anda harus secara eksplisit memberi tahu Android bahwa aplikasi memerlukan akses ke internet.
- Buka 
app/manifests/AndroidManifest.xml. Tambahkan baris ini sebelum tag<application>: 
<uses-permission android:name="android.permission.INTERNET" />- Kompilasi dan jalankan aplikasi lagi.  Jika semuanya berfungsi dengan benar dengan koneksi internet Anda, Anda akan melihat teks JSON yang berisi data Properti Mars.

 - Ketuk tombol Kembali di perangkat atau emulator untuk menutup aplikasi.
 - Aktifkan mode pesawat di perangkat atau emulator Anda, lalu buka kembali aplikasi dari menu Terbaru, atau mulai ulang aplikasi dari Android Studio.
 

- Nonaktifkan mode pesawat lagi.
 
Sekarang Anda mendapatkan respons JSON dari layanan web Mars, yang merupakan awal yang baik. Namun, yang benar-benar Anda butuhkan adalah objek Kotlin, bukan string JSON besar. Ada library bernama Moshi, yang merupakan parser JSON Android yang mengonversi string JSON menjadi objek Kotlin. Retrofit memiliki pengonversi yang berfungsi dengan Moshi, jadi ini adalah library yang bagus untuk tujuan Anda.
Dalam tugas ini, Anda menggunakan library Moshi dengan Retrofit untuk mengurai respons JSON dari layanan web menjadi objek Kotlin Mars Property yang berguna. Anda mengubah aplikasi sehingga tidak menampilkan JSON mentah, aplikasi akan menampilkan jumlah Properti Mars yang dikembalikan.
Langkah 1: Tambahkan dependensi library Moshi
- Buka build.gradle (Module: app).
 - Di bagian dependensi, tambahkan kode yang ditampilkan di bawah untuk menyertakan dependensi Moshi. Seperti Retrofit, 
$version_moshiditentukan secara terpisah dalam file Gradle level project. Dependensi ini menambahkan dukungan untuk library JSON Moshi inti, dan untuk dukungan Kotlin Moshi. 
implementation "com.squareup.moshi:moshi:$version_moshi"
implementation "com.squareup.moshi:moshi-kotlin:$version_moshi"- Temukan baris untuk pengonversi skalar Retrofit di blok 
dependencies: 
implementation "com.squareup.retrofit2:converter-scalars:$version_retrofit"- Ubah baris tersebut untuk menggunakan 
converter-moshi: 
implementation "com.squareup.retrofit2:converter-moshi:$version_retrofit"- Klik Sync Now untuk mem-build ulang project dengan dependensi baru.
 
Langkah 2: Menerapkan class data MarsProperty
Contoh entri respons JSON yang Anda dapatkan dari layanan web terlihat seperti ini:
[{"price":450000,
"id":"424906",
"type":"rent",
"img_src":"http://mars.jpl.nasa.gov/msl-raw-images/msss/01000/mcam/1000ML0044631300305227E03_DXXX.jpg"},
...]Respons JSON yang ditampilkan di atas adalah array, yang ditunjukkan dengan tanda kurung siku.  Array berisi objek JSON, yang dikelilingi oleh tanda kurung kurawal.  Setiap objek berisi serangkaian pasangan nama-nilai, yang dipisahkan oleh titik dua. Nama dikelilingi oleh tanda kutip. Nilai dapat berupa angka atau string, dan string juga diapit oleh tanda kutip. Misalnya, price untuk properti ini adalah $450.000 dan img_src adalah URL, yang merupakan lokasi file gambar di server. 
Pada contoh di atas, perhatikan bahwa setiap entri properti Mars memiliki pasangan kunci dan nilai JSON berikut:
price: harga properti Mars, sebagai angka.id: ID properti, sebagai string.type:"rent"atau"buy".img_src: URL gambar sebagai string.
Moshi mengurai data JSON ini dan mengubahnya menjadi objek Kotlin. Untuk melakukannya, library ini perlu memiliki class data Kotlin untuk menyimpan hasil yang diuraikan, sehingga langkah berikutnya adalah membuat class tersebut.
- Buka 
app/java/network/MarsProperty.kt. - Ganti definisi class 
MarsPropertyyang ada dengan kode berikut: 
data class MarsProperty(
   val id: String, val img_src: String,
   val type: String,
   val price: Double
)Perhatikan bahwa setiap variabel di class MarsProperty sesuai dengan nama kunci dalam objek JSON.  Untuk mencocokkan jenis dalam JSON, Anda menggunakan objek String untuk semua nilai kecuali price, yang merupakan Double.  Double dapat digunakan untuk merepresentasikan angka JSON apa pun.
Saat Moshi mengurai JSON, Moshi akan mencocokkan kunci berdasarkan nama dan mengisi objek data dengan nilai yang sesuai.
- Ganti baris untuk kunci 
img_srcdengan baris yang ditampilkan di bawah. Imporcom.squareup.moshi.Jsonbila diminta. 
@Json(name = "img_src") val imgSrcUrl: String,Terkadang nama kunci dalam respons JSON dapat membuat properti Kotlin membingungkan, atau mungkin tidak cocok dengan gaya coding Anda—misalnya, dalam file JSON, kunci img_src menggunakan garis bawah, sedangkan properti Kotlin biasanya menggunakan huruf besar dan huruf kecil ("camel case"). 
Untuk menggunakan nama variabel di class data yang berbeda dari nama kunci dalam respons JSON, gunakan anotasi @Json. Dalam contoh ini, nama variabel di class data adalah imgSrcUrl. Variabel dipetakan ke atribut JSON img_src menggunakan @Json(name = "img_src").
Langkah 3: Update MarsApiService dan OverviewViewModel
Dengan adanya class data MarsProperty, Anda kini dapat memperbarui API jaringan dan ViewModel untuk menyertakan data Moshi.  
- Buka 
network/MarsApiService.kt. Anda mungkin melihat error class tidak ada untukScalarsConverterFactory. Hal ini terjadi karena perubahan dependensi Retrofit yang Anda buat di Langkah 1. Anda akan segera memperbaiki error tersebut. - Di bagian atas file, tepat sebelum builder Retrofit, tambahkan kode berikut untuk membuat instance Moshi.  Impor 
com.squareup.moshi.Moshidancom.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactorybila diminta. 
private val moshi = Moshi.Builder()
   .add(KotlinJsonAdapterFactory())
   .build()Mirip dengan yang Anda lakukan dengan Retrofit, di sini Anda membuat objek moshi menggunakan builder Moshi.  Agar anotasi Moshi dapat berfungsi dengan baik dengan Kotlin, tambahkan KotlinJsonAdapterFactory, lalu panggil build().  
- Ubah builder Retrofit untuk menggunakan 
MoshiConverterFactory, bukanScalarConverterFactory, dan teruskan instancemoshiyang baru saja Anda buat. Imporretrofit2.converter.moshi.MoshiConverterFactorybila diminta. 
private val retrofit = Retrofit.Builder()
   .addConverterFactory(MoshiConverterFactory.create(moshi))
   .baseUrl(BASE_URL)
   .build()- Hapus juga impor untuk 
ScalarConverterFactory. 
Kode yang akan dihapus:
import retrofit2.converter.scalars.ScalarsConverterFactory- Perbarui antarmuka 
MarsApiServiceagar Retrofit menampilkan daftar objekMarsProperty, bukan menampilkanCall<String>. 
interface MarsApiService {
   @GET("realestate")
   fun getProperties():
      Call<List<MarsProperty>>
}- Buka 
OverviewViewModel.kt. Scroll ke bawah ke panggilan kegetProperties().enqueue()dalam metodegetMarsRealEstateProperties(). - Ubah argumen menjadi 
enqueue()dariCallback<String>menjadiCallback<List<MarsProperty>>. Imporcom.example.android.marsrealestate.network.MarsPropertybila diminta. 
MarsApi.retrofitService.getProperties().enqueue( 
   object: Callback<List<MarsProperty>> {- Di 
onFailure(), ubah argumen dariCall<String>menjadiCall<List<MarsProperty>>: 
override fun onFailure(call: Call<List<MarsProperty>>, t: Throwable) {- Lakukan perubahan yang sama pada kedua argumen ke 
onResponse(): 
override fun onResponse(call: Call<List<MarsProperty>>, 
   response: Response<List<MarsProperty>>) {- Di isi 
onResponse(), ganti tugas yang ada ke_response.valuedengan tugas yang ditunjukkan di bawah. Karenaresponse.body()sekarang berupa daftar objekMarsProperty, ukuran daftar tersebut adalah jumlah properti yang diuraikan. Pesan respons ini mencetak jumlah properti tersebut: 
_response.value = 
   "Success: ${response.body()?.size} Mars properties retrieved"- Pastikan mode pesawat dinonaktifkan.  Kompilasi dan jalankan aplikasi. Kali ini pesan akan menampilkan jumlah properti yang ditampilkan dari layanan web:

 
Sekarang layanan API Retrofit berjalan, tetapi menggunakan callback dengan dua metode callback yang harus Anda terapkan. Satu metode menangani keberhasilan dan metode lainnya menangani kegagalan, dan hasil kegagalan melaporkan pengecualian. Kode Anda akan lebih efisien dan lebih mudah dibaca jika Anda dapat menggunakan coroutine dengan penanganan pengecualian, bukan menggunakan callback. Untungnya, Retrofit memiliki library yang mengintegrasikan coroutine.
Dalam tugas ini, Anda akan mengonversi layanan jaringan dan ViewModel untuk menggunakan coroutine.  
Langkah 1: Tambahkan dependensi coroutine
- Buka build.gradle (Module: app).
 - Di bagian dependensi, tambahkan dukungan untuk library coroutine Kotlin inti dan library coroutine Retrofit:
 
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version_kotlin_coroutines" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version_kotlin_coroutines" implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:$version_retrofit_coroutines_adapter"
- Klik Sync Now untuk mem-build ulang project dengan dependensi baru.
 
Langkah 2: Perbarui MarsApiService dan OverviewViewModel
- Di 
MarsApiService.kt, perbarui builder Retrofit untuk menggunakanCoroutineCallAdapterFactory. Pembangun lengkap sekarang terlihat seperti ini: 
private val retrofit = Retrofit.Builder()
        .addConverterFactory(MoshiConverterFactory.create(moshi))
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .baseUrl(BASE_URL)
        .build()Adaptor panggilan menambahkan kemampuan Retrofit untuk membuat API yang menampilkan sesuatu selain class Call default.  Dalam hal ini, CoroutineCallAdapterFactory memungkinkan kita mengganti objek Call yang ditampilkan getProperties() dengan objek Deferred.
- Dalam metode 
getProperties(), ubahCall<List<MarsProperty>>menjadiDeferred<List<MarsProperty>>. Imporkotlinx.coroutines.Deferredbila diminta. MetodegetProperties()lengkap akan terlihat seperti ini: 
@GET("realestate")
fun getProperties():
   Deferred<List<MarsProperty>>Antarmuka Deferred menentukan tugas coroutine yang menampilkan nilai hasil (Deferred diwarisi dari Job). Antarmuka Deferred menyertakan metode yang disebut await(), yang menyebabkan kode Anda menunggu tanpa memblokir hingga nilai siap, lalu nilai tersebut ditampilkan. 
- Buka 
OverviewViewModel.kt. Tepat sebelum blokinit, tambahkan tugas coroutine: 
private var viewModelJob = Job()- Buat cakupan coroutine untuk tugas baru tersebut menggunakan dispatcher utama:
 
private val coroutineScope = CoroutineScope(
   viewModelJob + Dispatchers.Main )Dispatcher Dispatchers.Main menggunakan UI thread untuk tugasnya.  Karena Retrofit melakukan semua pekerjaannya di thread latar belakang, tidak ada alasan untuk menggunakan thread lain untuk cakupan. Hal ini memungkinkan Anda memperbarui nilai MutableLiveData dengan mudah saat mendapatkan hasil.
- Hapus semua kode di dalam 
getMarsRealEstateProperties(). Anda akan menggunakan coroutine di sini, bukan panggilan keenqueue()dan callbackonFailure()sertaonResponse(). - Di dalam 
getMarsRealEstateProperties(), luncurkan coroutine: 
coroutineScope.launch { 
}
Untuk menggunakan objek Deferred yang ditampilkan Retrofit untuk tugas jaringan, Anda harus berada di dalam coroutine, jadi di sini Anda meluncurkan coroutine yang baru saja dibuat.  Anda masih menjalankan kode di thread utama, tetapi sekarang Anda membiarkan coroutine mengelola konkurensi.
- Di dalam blok peluncuran, panggil 
getProperties()pada objekretrofitService: 
var getPropertiesDeferred = MarsApi.retrofitService.getProperties()Memanggil getProperties() dari layanan MarsApi akan membuat dan memulai panggilan jaringan di thread latar belakang, serta menampilkan objek Deferred untuk tugas tersebut. 
- Selain itu, di dalam blok peluncuran, tambahkan blok 
try/catchuntuk menangani pengecualian: 
try {
} catch (e: Exception) {
  
}- Di dalam blok 
try {}, panggilawait()pada objekDeferred: 
var listResult = getPropertiesDeferred.await()Memanggil await() pada objek Deferred akan menampilkan hasil dari panggilan jaringan saat nilai sudah siap. Metode await() tidak memblokir, sehingga layanan Mars API mengambil data dari jaringan tanpa memblokir thread saat ini—yang penting karena kita berada dalam cakupan thread UI. Setelah tugas selesai, kode Anda akan melanjutkan eksekusi dari tempat terakhir.  Hal ini berada di dalam try {} sehingga Anda dapat menangkap pengecualian.  
- Juga di dalam blok 
try {}, setelah metodeawait(), perbarui pesan respons untuk respons yang berhasil: 
_response.value = 
   "Success: ${listResult.size} Mars properties retrieved"- Di dalam blok 
catch {}, tangani respons kegagalan: 
_response.value = "Failure: ${e.message}"
Metode getMarsRealEstateProperties() lengkap kini terlihat seperti ini:
private fun getMarsRealEstateProperties() {
   coroutineScope.launch {
       var getPropertiesDeferred = 
          MarsApi.retrofitService.getProperties()
       try {          
           _response.value = 
              "Success: ${listResult.size} Mars properties retrieved"
       } catch (e: Exception) {
           _response.value = "Failure: ${e.message}"
       }
   }
}- Di bagian bawah class, tambahkan callback 
onCleared()dengan kode ini: 
override fun onCleared() {
   super.onCleared()
   viewModelJob.cancel()
}Pemuatan data harus berhenti saat ViewModel dihancurkan, karena OverviewFragment yang menggunakan ViewModel ini akan hilang. Untuk menghentikan pemuatan saat ViewModel dihancurkan, Anda mengganti onCleared() untuk membatalkan tugas.
- Kompilasi dan jalankan aplikasi. Anda akan mendapatkan hasil yang sama kali ini seperti pada tugas sebelumnya (laporan jumlah properti), tetapi dengan kode dan penanganan error yang lebih mudah.
 
Project Android Studio: MarsRealEstateNetwork
Layanan web REST
- Layanan web adalah layanan di internet yang memungkinkan aplikasi Anda membuat permintaan dan mendapatkan data kembali.
 - Layanan web umum menggunakan arsitektur REST. Layanan web yang menawarkan arsitektur REST disebut sebagai layanan RESTful. Layanan web RESTful dibuat menggunakan komponen dan protokol web standar.
 - Anda membuat permintaan ke layanan web REST dengan cara standar, melalui URI.
 - Untuk menggunakan layanan web, aplikasi harus membuat koneksi jaringan dan berkomunikasi dengan layanan. Kemudian, aplikasi harus menerima dan mengurai data respons ke dalam format yang dapat digunakan aplikasi.
 - Library Retrofit adalah library klien yang memungkinkan aplikasi Anda membuat permintaan ke layanan web REST.
 - Gunakan pengonversi untuk memberi tahu Retrofit apa yang harus dilakukan dengan data yang dikirimnya ke layanan web dan didapatkan kembali dari layanan web.  Misalnya, pengonversi 
ScalarsConvertermemperlakukan data layanan web sebagaiStringatau primitif lainnya. - Agar aplikasi Anda dapat terhubung ke internet, tambahkan izin 
"android.permission.INTERNET"dalam manifes Android. 
Penguraian JSON
- Respons dari layanan web sering kali diformat dalam JSON, format pertukaran umum untuk merepresentasikan data terstruktur.
 - Objek JSON adalah kumpulan pasangan nilai-kunci. Kumpulan ini terkadang disebut kamus, peta hash, atau array asosiatif.
 - Koleksi objek JSON adalah array JSON. Anda mendapatkan array JSON sebagai respons dari layanan web.
 - Kunci dalam pasangan nilai kunci dikelilingi oleh tanda kutip. Nilai dapat berupa angka atau string. String juga diapit oleh tanda kutip.
 - Library Moshi adalah parser JSON Android yang mengonversi string JSON menjadi objek Kotlin. Retrofit memiliki pengonversi yang berfungsi dengan Moshi.
 - Moshi mencocokkan kunci dalam respons JSON dengan properti dalam objek data yang memiliki nama yang sama.
 - Agar dapat menggunakan nama properti yang berbeda untuk sebuah kunci, anotasikan properti tersebut dengan anotasi 
@Jsondan nama kunci JSON. 
Retrofit dan coroutine
- Adaptor panggilan memungkinkan Retrofit membuat API yang menampilkan sesuatu selain class 
Calldefault. Gunakan classCoroutineCallAdapterFactoryuntuk menggantiCalldengan coroutineDeferred. - Gunakan metode 
await()pada objekDeferreduntuk membuat kode coroutine Anda menunggu tanpa memblokir hingga nilai siap, lalu nilai dikembalikan. 
Kursus Udacity:
Dokumentasi developer Android:
Dokumentasi Kotlin:
Lainnya:
Bagian ini mencantumkan kemungkinan tugas pekerjaan rumah untuk siswa yang mengerjakan codelab ini sebagai bagian dari kursus yang dipimpin oleh instruktur. Instruktur menentukan hal berikut:
- Memberikan pekerjaan rumah jika diperlukan.
 - Memberi tahu siswa cara mengirimkan tugas pekerjaan rumah.
 - Memberi nilai tugas pekerjaan rumah.
 
Instruktur bisa menggunakan saran ini sesuai kebutuhan, dan bebas menugaskan pekerjaan rumah lain yang dirasa cocok.
Jika Anda menyelesaikan codelab ini sendiri, gunakan tugas pekerjaan rumah ini untuk menguji pengetahuan Anda.
Jawab pertanyaan-pertanyaan berikut
Pertanyaan 1
Apa saja dua hal utama yang diperlukan Retrofit untuk membangun API layanan web?
▢ URI dasar untuk layanan web, dan kueri GET.
▢ URI dasar untuk layanan web, dan factory pelaku konversi.
▢ Koneksi jaringan ke layanan web, dan token otorisasi.
▢ Factory pelaku konversi, dan parser untuk respons.
Pertanyaan 2
Apa tujuan dari library Moshi?
▢ Untuk mendapatkan kembali data dari layanan web.
▢ Untuk berinteraksi dengan Retrofit agar dapat membuat permintaan layanan web.
▢ Untuk mengurai respons JSON dari layanan web ke objek data Kotlin.
▢ Untuk mengganti nama objek Kotlin agar sesuai dengan kunci di respons JSON.
Pertanyaan 3
Apa kegunaan adaptor panggilan Retrofit?
▢ Adaptor ini memungkinkan Retrofit menggunakan coroutine.
▢ Adaptor ini mengadaptasi respons layanan web ke dalam objek data Kotlin.
▢ Adaptor ini mengubah panggilan Retrofit menjadi panggilan layanan web.
▢ Adaptor ini menambahkan kemampuan untuk menampilkan sesuatu selain class Call default di Retrofit.
Mulai pelajaran berikutnya: 
Untuk link ke codelab lain dalam kursus ini, lihat halaman landing codelab Dasar-Dasar Android Kotlin.