Membuat Aplikasi Hello Android

Analisis Mendalam Kode Jetpack Compose

Jetpack Compose telah merevolusi cara pengembang Android membangun antarmuka pengguna (UI). Dengan pendekatan deklaratifnya, Compose memungkinkan kita untuk mendeskripsikan seperti apa UI kita seharusnya dalam keadaan tertentu, dan framework akan secara otomatis menanganinya.

Dalam artikel ini, kita akan melakukan analisis mendalam terhadap sebuah contoh kode aplikasi sederhana yang ditulis sepenuhnya menggunakan Jetpack Compose. Aplikasi ini menunjukkan beberapa konsep fundamental yang paling kuat, termasuk manajemen state, pembuatan daftar (list) yang efisien, dan animasi dasar.

Mari kita bedah kode tersebut bagian per bagian.

Struktur Utama Aplikasi: MainActivity dan MyApp

Setiap aplikasi dimulai dari sebuah Activity. Di sini, MainActivity berfungsi sebagai titik masuk (entry point).


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BasicsCodelabTheme {
                MyApp(modifier = Modifier.fillMaxSize())
            }
        }
    }
}
        

Fungsi setContent adalah jembatan antara dunia Android View klasik dan dunia Jetpack Compose. Di dalamnya, kita memanggil composable utama kita, yaitu MyApp, yang dibungkus oleh tema aplikasi (BasicsCodelabTheme).

Selanjutnya, mari kita lihat MyApp, yang merupakan inti dari logika navigasi aplikasi.


@Composable
fun MyApp(modifier: Modifier = Modifier) {
    var shouldShowOnboarding by rememberSaveable { mutableStateOf(true) }

    BackHandler(enabled = !shouldShowOnboarding) {
        shouldShowOnboarding = true
    }

    Surface(modifier) {
        if (shouldShowOnboarding) {
            OnboardingScreen(onContinueClicked = { shouldShowOnboarding = false })
        } else {
            Greetings()
        }
    }
}
        

Terdapat beberapa konsep kunci di sini:

  1. Manajemen State dengan rememberSaveable: Variabel shouldShowOnboarding menentukan layar mana yang akan ditampilkan.
    • mutableStateOf(true): Menciptakan sebuah state yang dapat diobservasi oleh Compose. Ketika nilainya berubah, setiap composable yang membacanya akan di-recompose (digambar ulang).
    • rememberSaveable: Ini adalah fungsi krusial. Tidak seperti remember, rememberSaveable akan menyimpan state tidak hanya selama recomposition, tetapi juga saat terjadi perubahan konfigurasi (seperti rotasi layar) atau saat proses aplikasi dihentikan oleh sistem.
  2. Conditional Rendering: Blok if/else sederhana digunakan untuk menampilkan OnboardingScreen atau Greetings berdasarkan nilai dari shouldShowOnboarding. Ini adalah inti dari UI deklaratif: deskripsikan UI untuk setiap state yang memungkinkan.
  3. BackHandler: Composable ini memberikan kontrol atas penekanan tombol kembali. enabled = !shouldShowOnboarding berarti BackHandler ini hanya aktif ketika kita tidak berada di layar onboarding. Saat tombol kembali ditekan di layar Greetings, ia akan mengubah state kembali ke true, sehingga menampilkan layar onboarding lagi.

Layar Onboarding: Interaksi Pengguna Sederhana

OnboardingScreen adalah composable yang sangat mendasar, yang dirancang untuk menampilkan pesan selamat datang dan sebuah tombol.


@Composable
fun OnboardingScreen(
    onContinueClicked: () -> Unit,
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier.fillMaxSize().fillMaxWidth(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(stringResource(R.string.welcome_text))
        Button(
            modifier = Modifier.padding(vertical = 24.dp),
            onClick = onContinueClicked
        ) {
            Text(stringResource(R.string.start_button))
        }
    }
}
        
  • Layout: Column digunakan untuk menyusun elemen secara vertikal. Dengan verticalArrangement = Arrangement.Center dan horizontalAlignment = Alignment.CenterHorizontally, konten di dalamnya akan diposisikan tepat di tengah layar.
  • Event Hoisting: Perhatikan parameter onContinueClicked: () -> Unit. OnboardingScreen tidak tahu apa yang harus dilakukan ketika tombol diklik. Ia hanya tahu bahwa ia harus memanggil fungsi onContinueClicked. Logika sebenarnya (mengubah shouldShowOnboarding menjadi false) berada di pemanggilnya, yaitu MyApp. Pola ini disebut event hoisting dan merupakan praktik terbaik di Compose untuk menjaga composable tetap reusable dan stateless.

Menampilkan Daftar yang Efisien dengan LazyColumn

Layar Greetings bertanggung jawab untuk menampilkan daftar nama yang panjang.


@Composable
private fun Greetings(
    modifier: Modifier = Modifier,
    names: List<String> = List(1000) { "$it" }
) {
    LazyColumn(modifier = modifier.padding(vertical = 4.dp)) {
        items(items = names) { name ->
            Greeting(name = name)
        }
    }
}
        

Jika kita menggunakan Column biasa untuk menampilkan 1000 item, aplikasi akan mengalami masalah performa yang serius karena semua 1000 item akan di-render sekaligus. Solusinya adalah LazyColumn.

LazyColumn bekerja seperti RecyclerView pada sistem View. Ia hanya me-render item yang terlihat di layar, ditambah beberapa item di luar layar sebagai buffer. Ini memastikan performa yang sangat efisien bahkan untuk daftar yang sangat panjang.

Elemen Daftar Interaktif dan Animasi

Setiap item dalam daftar adalah Greeting, yang pada dasarnya adalah sebuah Card yang dapat diperluas.


@Composable
private fun Greeting(name: String, modifier: Modifier = Modifier) {
    Card(...) {
        CardContent(name)
    }
}

@Composable
private fun CardContent(name: String) {
    var expanded by rememberSaveable { mutableStateOf(false) }

    Row(
        modifier = Modifier
            .padding(12.dp)
            .animateContentSize(...)
    ) {
        Column(modifier = Modifier.weight(1f)...) {
            // ... Teks standar
            if (expanded) {
                Text(...)
            }
        }
        IconButton(onClick = { expanded = !expanded }) {
            // ... Ikon
        }
    }
}
        

Analisis CardContent mengungkapkan beberapa teknik Compose yang elegan:

  • State Lokal: Setiap CardContent memiliki state expanded-nya sendiri, yang disimpan menggunakan rememberSaveable. Ini berarti setiap kartu dalam daftar mengelola status diperluas/diciutkannya secara independen.
  • Layout Kompleks: Kombinasi Row dan Column digunakan untuk menyusun tata letak. Modifier.weight(1f) pada Column membuatnya mengisi semua ruang horizontal yang tersedia di dalam Row, mendorong IconButton ke tepi kanan.
  • Animasi Implisit dengan animateContentSize: Ini adalah salah satu fitur paling mengesankan. Dengan hanya menambahkan modifier animateContentSize pada Row, Compose secara otomatis akan menganimasikan perubahan ukuran Row tersebut. Ketika state expanded berubah, teks tambahan akan muncul atau hilang. Modifier ini menangani transisi ukuran yang mulus tanpa perlu menulis kode animasi yang rumit.
  • Logika Tampilan Kondisional: Sama seperti di MyApp, blok if (expanded) digunakan untuk menampilkan konten tambahan secara kondisional. Ikon pada IconButton juga berubah berdasarkan state ini.

Pentingnya Pratinjau (@Preview)


@Preview(showBackground = true, widthDp = 320)
@Composable
fun GreetingPreview() {
    BasicsCodelabTheme {
        Greetings()
    }
}
        

Anotasi @Preview adalah alat pengembangan yang sangat kuat. Ini memungkinkan pengembang untuk melihat tampilan composable mereka langsung di dalam Android Studio tanpa perlu menjalankan aplikasi pada emulator atau perangkat fisik. Ini secara drastis mempercepat siklus iterasi desain UI. Parameter seperti widthDp, heightDp, dan uiMode = UI_MODE_NIGHT_YES memungkinkan kita untuk menguji composable dalam berbagai konfigurasi.

Kesimpulan

Meskipun terlihat sederhana, kode aplikasi ini adalah demonstrasi yang sangat baik dari kekuatan dan keanggunan Jetpack Compose. Ia mencakup konsep-konsep inti yang membentuk landasan pengembangan UI modern di Android:

  • Paradigma Deklaratif: Mendeskripsikan UI berdasarkan state.
  • Manajemen State: Menggunakan rememberSaveable untuk state yang persisten dan dapat diobservasi.
  • Komposisi: Membangun UI yang kompleks dari fungsi-fungsi composable yang lebih kecil dan dapat digunakan kembali.
  • Event Hoisting: Memisahkan logika dari presentasi untuk komponen yang lebih bersih.
  • Performa: Menggunakan LazyColumn untuk daftar yang efisien.
  • Animasi: Mengintegrasikan animasi yang kaya dengan mudah menggunakan modifier seperti animateContentSize.

Dengan memahami blok bangunan fundamental ini, pengembang dapat mulai membangun aplikasi Android yang kompleks, reaktif, dan indah dengan lebih cepat dan lebih sedikit kode.

Link Github

Referensi:

https://kuliahppb.blogspot.com/2024/03/android-1-jetpack-compose.html

https://developer.android.com/codelabs/jetpack-compose-basics

Komentar

Postingan populer dari blog ini

Tugas 10: Membuat Aplikasi Unscramble

ETS Proyek 5: Aplikasi Galeri Foto Pribadi

Evaluasi Akhir Semester