1. Sebelum memulai
Pengantar
Dalam codelab sebelumnya, Anda telah mempelajari cara mendapatkan data dari layanan web menggunakan pola repositori dan mengurai respons menjadi objek Kotlin. Dalam codelab ini, Anda menggunakan pengetahuan tersebut untuk memuat dan menampilkan foto dari URL web. Anda juga meninjau kembali cara membuat LazyVerticalGrid
dan menggunakannya untuk menampilkan petak gambar pada halaman ringkasan.
Prasyarat
- Mengetahui cara mengambil JSON dari layanan web REST dan penguraian data tersebut menjadi objek Kotlin menggunakan library Retrofit dan Gson
- Mengetahui layanan web REST
- Memahami komponen arsitektur Android, seperti lapisan data dan repositori
- Mengetahui injeksi dependensi
- Mengetahui
ViewModel
danViewModelProvider.Factory
- Mengetahui implementasi coroutine untuk aplikasi
- Mengetahui pola repositori
Yang akan Anda pelajari
- Cara menggunakan library Coil untuk memuat dan menampilkan gambar dari URL web.
- Cara menggunakan
LazyVerticalGrid
untuk menampilkan petak gambar. - Cara menangani potensi error saat gambar didownload dan ditampilkan.
Yang akan Anda build
- Memodifikasi aplikasi Mars Photos untuk mendapatkan URL gambar dari data Mars, dan menggunakan Coil untuk memuat dan menampilkan gambar itu.
- Menambahkan animasi pemuatan dan ikon error ke aplikasi.
- Menambahkan penanganan status dan error ke aplikasi.
Yang Anda butuhkan
- Komputer dengan browser web modern, seperti Chrome versi terbaru
- Kode awal untuk aplikasi Mars Photosdengan layanan web REST
2. Ringkasan aplikasi
Dalam codelab ini, Anda akan kembali menggunakan aplikasi Mars Photos dari codelab sebelumnya. Aplikasi Mars Photos terhubung ke layanan web untuk mengambil dan menampilkan jumlah objek Kotlin yang diambil menggunakan Gson. Objek Kotlin ini berisi URL foto kehidupan nyata dari permukaan Mars yang diambil dari Wahana Penjelajah Mars (Mars Rover) NASA.
Versi aplikasi yang Anda bangun di codelab ini menampilkan foto Mars dalam petak gambar. Gambar tersebut merupakan bagian dari data yang diambil aplikasi Anda dari layanan web. Aplikasi Anda akan menggunakan library Coil untuk memuat dan menampilkan gambar, serta LazyVerticalGrid
untuk membuat tata letak petak untuk gambar. Aplikasi Anda juga akan menangani error jaringan secara halus dengan menampilkan pesan error.
Mendapatkan kode awal
Untuk memulai, download kode awal:
Atau, Anda dapat membuat clone repositori GitHub untuk kode tersebut:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-mars-photos.git $ cd basic-android-kotlin-compose-training-mars-photos $ git checkout coil-starter
Anda dapat menjelajahi kode di repositori GitHub Mars Photos
.
3. Menampilkan gambar yang didownload
Menampilkan foto dari URL web mungkin terdengar mudah, tetapi ada sedikit teknik untuk membuatnya berfungsi dengan baik. Gambar harus didownload, disimpan secara internal (di-cache), dan didekode-kan dari format terkompresi menjadi gambar yang dapat digunakan Android. Anda dapat meng-cache gambar ke cache dalam memori, cache berbasis penyimpanan, atau keduanya. Semua proses ini harus berlangsung di thread latar belakang prioritas rendah agar UI tetap responsif. Selain itu, untuk performa jaringan dan CPU terbaik, Anda dapat mengambil dan mendekode lebih dari satu gambar sekaligus.
Untungnya, Anda dapat menggunakan library yang dikembangkan komunitas yang disebut Coil untuk mendownload, melakukan buffering, mendekode, dan meng-cache gambar Anda. Tanpa menggunakan Coil, Anda akan memiliki lebih banyak pekerjaan yang harus dilakukan.
Coil pada dasarnya memerlukan dua hal:
- URL gambar yang ingin Anda muat dan tampilkan.
- Composable
AsyncImage
untuk benar-benar menampilkan gambar tersebut.
Dalam tugas ini, Anda akan mempelajari cara menggunakan Coil untuk menampilkan satu gambar dari layanan web Mars. Anda menampilkan gambar foto Mars pertama dalam daftar foto yang ditampilkan oleh layanan web. Gambar berikut menampilkan screenshot sebelum dan sesudah:
Menambahkan dependensi Coil
- Buka aplikasi solusi Mars Photos dari codelab Menambahkan repositori dan DI Manual.
- Jalankan aplikasi untuk mengonfirmasi bahwa aplikasi menampilkan jumlah foto Mars yang diambil.
- Buka build.gradle.kts (Module :app).
- Di bagian
dependencies
, tambahkan baris ini untuk library Coil:
// Coil
implementation("io.coil-kt:coil-compose:2.4.0")
Periksa dan update versi terbaru library dari halaman dokumentasi Coil.
- Klik Sync Now untuk membuat ulang project dengan dependensi baru.
Menampilkan URL Gambar
Pada langkah ini, Anda akan mengambil dan menampilkan URL foto pertama Mars.
- Pada
ui/screens/MarsViewModel.kt
, di dalam metodegetMarsPhotos()
, di dalam bloktry
, cari baris yang menetapkan data yang diambil dari layanan web menjadilistResult
.
// No need to copy, code is already present
try {
val listResult = marsPhotosRepository.getMarsPhotos()
//...
}
- Perbarui baris ini dengan mengubah
listResult
menjadiresult
dan menetapkan foto pertama Mars yang diambil ke variabel baruresult
. Tetapkan objek foto pertama di indeks0
.
try {
val result = marsPhotosRepository.getMarsPhotos()[0]
//...
}
- Pada baris berikutnya, perbarui parameter yang diteruskan ke panggilan fungsi
MarsUiState.Success()
ke string dalam kode berikut. Gunakan data dari properti baru, bukanlistResult
. Tampilkan URL gambar pertama dari fotoresult
.
try {
...
MarsUiState.Success("First Mars image URL: ${result.imgSrc}")
}
Blok try
lengkap kini terlihat seperti kode berikut:
marsUiState = try {
val result = marsPhotosRepository.getMarsPhotos()[0]
MarsUiState.Success(
" First Mars image URL : ${result.imgSrc}"
)
}
- Jalankan aplikasi. Composable
Text
kini menampilkan URL foto pertama Mars. Bagian berikutnya menjelaskan cara membuat aplikasi menampilkan gambar di URL ini.
Menambahkan composable AsyncImage
Pada langkah ini, Anda akan menambahkan fungsi composable AsyncImage
untuk memuat dan menampilkan satu foto Mars. AsyncImage
adalah composable yang menjalankan permintaan gambar secara asinkron lalu merender hasilnya.
// Example code, no need to copy over
AsyncImage(
model = "https://android.com/sample_image.jpg",
contentDescription = null
)
Argumen model
dapat berupa nilai ImageRequest.data
atau ImageRequest
. Pada contoh sebelumnya, Anda menetapkan nilai ImageRequest.data
—yaitu, URL gambar, yaitu "https://android.com/sample_image.jpg"
. Kode contoh berikut menunjukkan cara menetapkan ImageRequest
ke model
.
// Example code, no need to copy over
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data("https://example.com/image.jpg")
.crossfade(true)
.build(),
placeholder = painterResource(R.drawable.placeholder),
contentDescription = stringResource(R.string.description),
contentScale = ContentScale.Crop,
modifier = Modifier.clip(CircleShape)
)
AsyncImage
mendukung argumen yang sama seperti composable Image standar. Selain itu, composable ini mendukung penyetelan painter placeholder
/error
/fallback
dan callback onLoading
/onSuccess
/onError
. Kode contoh sebelumnya memuat gambar dengan pemangkasan lingkaran dan crossfade, dan menetapkan placeholder.
contentDescription
menetapkan teks yang digunakan oleh layanan aksesibilitas untuk mendeskripsikan item yang diwakili oleh gambar ini.
Tambahkan composable AsyncImage
ke kode Anda untuk menampilkan foto pertama Mars yang diambil.
- Di
ui/screens/HomeScreen.kt
, tambahkan fungsi composable baru yang disebutMarsPhotoCard()
, yang menggunakanMarsPhoto
danModifier
.
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
}
- Di dalam fungsi composable
MarsPhotoCard()
, tambahkan fungsiAsyncImage()
sebagai berikut:
import coil.compose.AsyncImage
import coil.request.ImageRequest
import androidx.compose.ui.platform.LocalContext
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.build(),
contentDescription = stringResource(R.string.mars_photo),
modifier = Modifier.fillMaxWidth()
)
}
Pada kode sebelumnya, Anda mem-build ImageRequest
menggunakan URL gambar (photo.imgSrc
) dan meneruskannya ke argumen model
. Anda menggunakan contentDescription
untuk menetapkan teks bagi pembaca aksesibilitas.
- Tambahkan
crossfade(true)
keImageRequest
untuk mengaktifkan animasi crossfade saat permintaan berhasil diselesaikan.
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.crossfade(true)
.build(),
contentDescription = stringResource(R.string.mars_photo),
modifier = Modifier.fillMaxWidth()
)
}
- Perbarui composable
HomeScreen
untuk menampilkan composableMarsPhotoCard
, bukan composableResultScreen
, saat permintaan berhasil diselesaikan. Anda dapat memperbaiki error ketidakcocokan jenis pada langkah berikutnya.
@Composable
fun HomeScreen(
marsUiState: MarsUiState,
modifier: Modifier = Modifier
) {
when (marsUiState) {
is MarsUiState.Loading -> LoadingScreen(modifier = modifier.fillMaxSize())
is MarsUiState.Success -> MarsPhotoCard(photo = marsUiState.photos, modifier = modifier.fillMaxSize())
else -> ErrorScreen(modifier = modifier.fillMaxSize())
}
}
- Dalam file
MarsViewModel.kt
, perbarui antarmukaMarsUiState
agar dapat menerima objekMarsPhoto
, bukanString
.
sealed interface MarsUiState {
data class Success(val photos: MarsPhoto) : MarsUiState
//...
}
- Perbarui fungsi
getMarsPhotos()
untuk meneruskan objek foto pertama Mars keMarsUiState.Success()
. Hapus variabelresult
.
marsUiState = try {
MarsUiState.Success(marsPhotosRepository.getMarsPhotos()[0])
}
- Jalankan aplikasi dan konfirmasi bahwa aplikasi menampilkan satu gambar Mars.
- Foto Mars tidak memenuhi seluruh layar. Untuk mengisi ruang yang tersedia di layar, pada
HomeScreen.kt
diAsyncImage
, aturcontentScale
keContentScale.Crop
.
import androidx.compose.ui.layout.ContentScale
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.crossfade(true)
.build(),
contentDescription = stringResource(R.string.mars_photo),
contentScale = ContentScale.Crop,
modifier = modifier,
)
}
- Jalankan aplikasi dan konfirmasi bahwa gambar telah mengisi layar secara horizontal dan vertikal.
Menambahkan gambar pemuatan dan error
Anda dapat meningkatkan kualitas pengalaman pengguna di aplikasi dengan menampilkan gambar placeholder saat memuat gambar. Anda juga dapat menampilkan gambar error jika pemuatan gagal karena masalah, seperti file gambar yang hilang atau rusak. Di bagian ini, Anda akan menambahkan gambar error dan placeholder menggunakan AsyncImage
.
- Buka
res/drawable/ic_broken_image.xml
lalu klik tab Design atau Split di sebelah kanan. Untuk gambar error, gunakan ikon gambar rusak yang tersedia di library ikon bawaan. Vektor drawable ini menggunakan atributandroid:tint
untuk mewarnai ikon menjadi abu-abu.
- Buka
res/drawable/loading_img.xml
. Drawable ini adalah animasi yang memutar drawable gambar,loading_img.xml
, mengitari titik tengah. (Anda tidak melihat animasinya di pratinjau.)
- Kembali ke file
HomeScreen.kt
. Di composableMarsPhotoCard
, perbarui panggilan keAsyncImage()
untuk menambahkan atributerror
danplaceholder
seperti yang ditunjukkan dalam kode berikut:
import androidx.compose.ui.res.painterResource
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
// ...
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
// ...
)
}
Kode ini menetapkan gambar pemuatan placeholder yang akan digunakan saat memuat (drawable loading_img
). Kode ini juga menetapkan gambar yang akan digunakan jika pemuatan gambar gagal (drawable ic_broken_image
).
Composable MarsPhotoCard
lengkap kini terlihat seperti kode berikut:
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.crossfade(true)
.build(),
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
contentDescription = stringResource(R.string.mars_photo),
contentScale = ContentScale.Crop
)
}
- Jalankan aplikasi. Bergantung pada kecepatan koneksi jaringan, Anda mungkin melihat gambar pemuatan secara cepat saat Coil mendownload dan menampilkan gambar properti. Anda tidak akan melihat ikon gambar yang rusak meskipun jaringan dinonaktifkan—Anda akan memperbaiki error di tugas terakhir codelab.
4. Menampilkan petak gambar dengan LazyVerticalGrid
Sekarang aplikasi Anda memuat foto Mars dari internet, item daftar MarsPhoto
pertama. Anda telah menggunakan URL gambar dari data foto Mars tersebut untuk mengisi AsyncImage
. Namun, tujuannya adalah agar aplikasi Anda menampilkan petak gambar. Dalam tugas ini, Anda menggunakan LazyVerticalGrid
dengan pengelola tata letak Grid untuk menampilkan petak gambar.
Petak lambat
Composable LazyVerticalGrid dan LazyHorizontalGrid memberikan dukungan untuk menampilkan item dalam petak. Petak vertikal lambat menampilkan itemnya dalam penampung yang dapat di-scroll secara vertikal dan dibentangkan di beberapa kolom, sedangkan petak horizontal lambat memiliki perilaku yang sama pada sumbu horizontal.
Dari perspektif desain, Tata Letak Grid paling tepat digunakan untuk menampilkan foto Mars sebagai ikon atau gambar.
Parameter columns
di parameter LazyVerticalGrid
dan rows
di LazyHorizontalGrid
mengontrol cara pembentukan sel menjadi kolom atau baris. Kode contoh berikut menampilkan item dalam petak, menggunakan GridCells.Adaptive
untuk menetapkan lebar masing-masing kolom minimal 128.dp
:
// Sample code - No need to copy over
@Composable
fun PhotoGrid(photos: List<Photo>) {
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 150.dp)
) {
items(photos) { photo ->
PhotoItem(photo)
}
}
}
LazyVerticalGrid
memungkinkan Anda menentukan lebar item, lalu petak akan sesuai dengan sebanyak mungkin kolom. Setelah menghitung jumlah kolom, petak akan mendistribusikan lebar yang tersisa di antara kolom secara merata. Cara adaptif pengukuran ini sangat berguna untuk menampilkan kumpulan item di berbagai ukuran layar.
Dalam codelab ini, Anda dapat menggunakan composable LazyVerticalGrid
dengan GridCells.Adaptive
, dengan setiap kolom ditetapkan ke lebar 150.dp
, untuk menampilkan foto Mars.
Kunci item
Saat pengguna men-scroll petak (LazyRow
dalam LazyColumn
), posisi item daftar akan berubah. Namun, karena adanya perubahan orientasi atau jika item ditambahkan atau dihapus, pengguna dapat kehilangan posisi scroll dalam baris. Kunci item membantu Anda mempertahankan posisi scroll berdasarkan kunci.
Dengan menyediakan kunci, Anda membantu Compose menangani pengurutan ulang dengan benar. Misalnya, jika item Anda berisi status yang diingat, kunci setelan akan memungkinkan Compose memindahkan status ini bersama item tersebut saat posisinya berubah.
Menambahkan LazyVerticalGrid
Tambahkan composable untuk menampilkan daftar foto Mars dalam petak vertikal.
- Dalam file
HomeScreen.kt
, buat fungsi composable baru bernamaPhotosGridScreen()
yang menggunakan daftarMarsPhoto
danmodifier
sebagai argumen.
@Composable
fun PhotosGridScreen(
photos: List<MarsPhoto>,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
) {
}
- Di dalam composable
PhotosGridScreen
, tambahkanLazyVerticalGrid
dengan parameter berikut.
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.ui.unit.dp
@Composable
fun PhotosGridScreen(
photos: List<MarsPhoto>,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
) {
LazyVerticalGrid(
columns = GridCells.Adaptive(150.dp),
modifier = modifier.padding(horizontal = 4.dp),
contentPadding = contentPadding,
) {
}
}
- Untuk menambahkan daftar item, di dalam lambda
LazyVerticalGrid
, panggil fungsiitems()
yang meneruskan daftarMarsPhoto
dan kunci item sebagaiphoto.id
.
import androidx.compose.foundation.lazy.grid.items
@Composable
fun PhotosGridScreen(
photos: List<MarsPhoto>,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
) {
LazyVerticalGrid(
// ...
) {
items(items = photos, key = { photo -> photo.id }) {
}
}
}
- Untuk menambahkan konten yang ditampilkan oleh satu item daftar, tentukan ekspresi lambda
items
. PanggilMarsPhotoCard
dengan meneruskanphoto
.
items(items = photos, key = { photo -> photo.id }) {
photo -> MarsPhotoCard(photo)
}
- Perbarui composable
HomeScreen
untuk menampilkan composablePhotosGridScreen
, bukan composableMarsPhotoCard
, agar permintaan berhasil diselesaikan.
when (marsUiState) {
// ...
is MarsUiState.Success -> PhotosGridScreen(marsUiState.photos, modifier)
// ...
}
- Dalam file
MarsViewModel.kt
, perbarui antarmukaMarsUiState
untuk menerima daftar objekMarsPhoto
, bukanMarsPhoto
tunggal. ComposablePhotosGridScreen
menerima daftar objekMarsPhoto
.
sealed interface MarsUiState {
data class Success(val photos: List<MarsPhoto>) : MarsUiState
//...
}
- Di file
MarsViewModel.kt
, perbarui fungsigetMarsPhotos()
untuk meneruskan daftar objek foto Mars keMarsUiState.Success()
.
marsUiState = try {
MarsUiState.Success(marsPhotosRepository.getMarsPhotos())
}
- Jalankan aplikasi.
Perhatikan bahwa tidak ada padding di sekitar setiap foto, dan rasio aspek juga berbeda untuk foto yang berbeda. Anda dapat menambahkan composable Card
untuk memperbaiki masalah ini.
Menambahkan composable card
- Di file
HomeScreen.kt
, di composableMarsPhotoCard
, tambahkanCard
dengan elevasi8.dp
di sekitarAsyncImage
. Tetapkan argumenmodifier
ke composableCard
.
import androidx.compose.material.Card
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.padding
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
Card(
modifier = modifier,
elevation = CardDefaults.cardElevation(defaultElevation = 8.dp)
) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.crossfade(true)
.build(),
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
contentDescription = stringResource(R.string.mars_photo),
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxWidth()
)
}
}
- Untuk memperbaiki rasio aspek, di
PhotosGridScreen()
, perbarui pengubah untukMarsPhotoCard()
.
@Composable
fun PhotosGridScreen(photos: List<MarsPhoto>, modifier: Modifier = Modifier) {
LazyVerticalGrid(
//...
) {
items(items = photos, key = { photo -> photo.id }) { photo ->
MarsPhotoCard(
photo,
modifier = modifier
.padding(4.dp)
.fillMaxWidth()
.aspectRatio(1.5f)
)
}
}
}
- Perbarui pratinjau layar hasil untuk melihat pratinjau
PhotosGridScreen()
. Tirukan data dengan URL gambar kosong.
@Preview(showBackground = true) @Composable fun PhotosGridScreenPreview() { MarsPhotosTheme { val mockData = List(10) { MarsPhoto("$it", "") } PhotosGridScreen(mockData) } }
Data tiruan memiliki URL kosong sehingga Anda akan melihat gambar yang dimuat di pratinjau petak foto.
- Jalankan aplikasi.
- Saat aplikasi berjalan, aktifkan Mode Pesawat.
- Scroll gambar di emulator. Gambar yang belum dimuat akan muncul sebagai ikon gambar yang rusak. Ini adalah drawable gambar yang telah Anda teruskan ke library gambar Coil untuk ditampilkan jika terjadi error jaringan atau gambar tidak bisa diambil.
Bagus! Anda telah menyimulasikan error koneksi jaringan dengan mengaktifkan Mode Pesawat di emulator atau perangkat.
5. Tambahkan tindakan coba lagi
Di bagian ini, Anda akan menambahkan tombol tindakan coba lagi dan mengambil foto saat tombol diklik.
- Tambahkan tombol ke layar error. Dalam file
HomeScreen.kt
, update composableErrorScreen()
untuk menyertakan parameter lambdaretryAction
dan tombol.
@Composable
fun ErrorScreen(retryAction: () -> Unit, modifier: Modifier = Modifier) {
Column(
// ...
) {
Image(
// ...
)
Text(//...)
Button(onClick = retryAction) {
Text(stringResource(R.string.retry))
}
}
}
Periksa pratinjau.
- Perbarui composable
HomeScreen()
untuk meneruskan lambda coba lagi.
@Composable
fun HomeScreen(
marsUiState: MarsUiState, retryAction: () -> Unit, modifier: Modifier = Modifier
) {
when (marsUiState) {
//...
is MarsUiState.Error -> ErrorScreen(retryAction, modifier = modifier.fillMaxSize())
}
}
- Pada file
ui/theme/MarsPhotosApp.kt
, update panggilan fungsiHomeScreen()
untuk menetapkan parameter lambdaretryAction
kemarsViewModel::getMarsPhotos
. Tindakan ini akan mengambil foto mars dari server.
HomeScreen(
marsUiState = marsViewModel.marsUiState,
retryAction = marsViewModel::getMarsPhotos
)
6. Memperbarui pengujian ViewModel
MarsUiState
dan MarsViewModel
kini mengakomodasi daftar foto, bukan hanya satu foto. Dalam statusnya saat ini, MarsViewModelTest
mengharapkan class data MarsUiState.Success
berisi properti string. Oleh karena itu, pengujian tidak dikompilasi. Anda harus memperbarui pengujian marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess()
untuk menyatakan bahwa MarsViewModel.marsUiState
sama dengan status Success
yang berisi daftar foto.
- Buka file
rules/MarsViewModelTest.kt
. - Pada pengujian
marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess()
, ubah panggilan fungsiassertEquals()
untuk membandingkan statusSuccess
(meneruskan daftar foto palsu ke parameter foto) kemarsViewModel.marsUiState
.
@Test
fun marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess() =
runTest {
val marsViewModel = MarsViewModel(
marsPhotosRepository = FakeNetworkMarsPhotosRepository()
)
assertEquals(
MarsUiState.Success(FakeDataSource.photosList),
marsViewModel.marsUiState
)
}
Sekarang pengujiannya bisa dikompilasi, berjalan, dan berhasil.
7. Mendapatkan kode solusi
Guna mendownload kode untuk codelab yang sudah selesai, Anda dapat menggunakan perintah git ini:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-mars-photos.git
Atau, Anda dapat mendownload repositori sebagai file ZIP, lalu mengekstraknya, dan membukanya di Android Studio.
Jika Anda ingin melihat kode solusi untuk codelab ini, lihat kode tersebut di GitHub.
8. Kesimpulan
Selamat karena telah menyelesaikan codelab ini dan membuat aplikasi Mars Photos. Kini saatnya memperlihatkan aplikasi Anda dengan gambar Mars nyata kepada keluarga dan teman Anda.
Jangan lupa untuk membagikan karya Anda di media sosial dengan #AndroidBasics!
9. Mempelajari lebih lanjut
Dokumentasi developer Android:
- Daftar dan petak | Jetpack Compose | Android Developers
- Petak lambat | Jetpack Compose | Android Developers
- Ringkasan ViewModel
Lainnya: