Dasar-Dasar Android Kotlin 02.4: Dasar-dasar data binding

Codelab ini adalah bagian dari kursus Dasar-Dasar Kotlin Android. Anda akan mendapatkan manfaat maksimal dari kursus ini jika Anda mengerjakan codelab secara berurutan. Semua codelab kursus tercantum di halaman landing codelab Dasar-Dasar Android Kotlin.

Pengantar

Pada codelab sebelumnya di kursus ini, Anda menggunakan fungsi findViewById() untuk mendapatkan referensi ke tampilan. Saat aplikasi Anda memiliki hierarki tampilan yang kompleks, findViewById() mahal dan memperlambat aplikasi, karena Android melintasi hierarki tampilan, mulai dari root, hingga menemukan tampilan yang diinginkan. Untungnya, ada cara yang lebih baik.

Untuk menyetel data dalam tampilan, Anda harus menggunakan resource string dan menyetel data dari aktivitas. Akan lebih efisien jika tampilan tersebut mengetahui data. Dan untungnya lagi, hal ini mungkin dilakukan.

Dalam codelab ini, Anda akan mempelajari cara menggunakan data binding untuk menghilangkan kebutuhan akan findViewById(). Anda juga akan mempelajari cara menggunakan data binding untuk mengakses data langsung dari tampilan.

Yang harus sudah Anda ketahui

Anda harus memahami:

  • Pengertian aktivitas, dan cara menyiapkan aktivitas dengan tata letak di onCreate().
  • Membuat tampilan teks dan menyetel teks yang ditampilkan tampilan teks.
  • Menggunakan findViewById() untuk mendapatkan referensi ke tampilan.
  • Membuat dan mengedit tata letak XML dasar untuk tampilan.

Yang akan Anda pelajari

  • Cara menggunakan Library Data Binding untuk menghilangkan panggilan yang tidak efisien ke findViewById().
  • Cara mengakses data aplikasi langsung dari XML.

Yang akan Anda lakukan

  • Mengubah aplikasi agar menggunakan data binding, bukan findViewById(), serta untuk mengakses data langsung dari file XML tata letak.

Dalam codelab ini, Anda akan memulai dengan aplikasi AboutMe dan mengubah aplikasi untuk menggunakan data binding. Aplikasi akan terlihat sama persis setelah Anda selesai!

Berikut fungsi aplikasi AboutMe:

  • Saat pengguna membuka aplikasi, aplikasi akan menampilkan nama, kolom untuk memasukkan nama panggilan, tombol Selesai, gambar bintang, dan teks yang dapat di-scroll.
  • Pengguna dapat memasukkan nama panggilan dan mengetuk tombol Selesai. Tombol dan kolom yang dapat diedit diganti dengan tampilan teks yang menampilkan nama panggilan yang dimasukkan.


Anda dapat menggunakan kode yang dibuat di codelab sebelumnya, atau Anda dapat mendownload kode AboutMeDataBinding-Starter dari GitHub.

Kode yang Anda tulis di codelab sebelumnya menggunakan fungsi findViewById() untuk mendapatkan referensi ke tampilan.

Setiap kali Anda menggunakan findViewById() untuk menelusuri tampilan setelah tampilan dibuat atau dibuat ulang, sistem Android akan melintasi hierarki tampilan saat runtime untuk menemukannya. Ketika aplikasi Anda hanya memiliki sedikit tampilan, ini bukan masalah. Namun, aplikasi produksi mungkin memiliki puluhan tampilan dalam tata letak, dan bahkan dengan desain terbaik, akan ada tampilan bertingkat.

Bayangkan tata letak linier yang berisi tampilan scroll yang berisi tampilan teks. Untuk hierarki tampilan yang besar atau dalam, menemukan tampilan dapat memakan waktu yang cukup lama sehingga dapat memperlambat aplikasi untuk pengguna. Menyimpan tampilan ke dalam cache dalam variabel dapat membantu, tetapi Anda tetap harus menginisialisasi variabel untuk setiap tampilan, di setiap namespace. Dengan banyaknya penayangan dan berbagai aktivitas, jumlah ini juga akan bertambah.

Salah satu solusinya adalah membuat objek yang berisi referensi ke setiap tampilan. Objek ini, yang disebut objek Binding, dapat digunakan oleh seluruh aplikasi Anda. Teknik ini disebut data binding. Setelah objek binding dibuat untuk aplikasi, Anda dapat mengakses tampilan, dan data lain, melalui objek binding, tanpa harus menjelajahi hierarki tampilan atau menelusuri data.

Data binding memiliki manfaat berikut:

  • Kode lebih pendek, lebih mudah dibaca, dan lebih mudah dikelola daripada kode yang menggunakan findByView().
  • Data dan tampilan dipisahkan dengan jelas. Manfaat binding data ini menjadi semakin penting nantinya dalam kursus ini.
  • Sistem Android hanya melintasi hierarki tampilan sekali untuk mendapatkan setiap tampilan, dan ini terjadi selama startup aplikasi, bukan pada waktu proses saat pengguna berinteraksi dengan aplikasi.
  • Anda mendapatkan keamanan jenis untuk mengakses tampilan. (Keamanan jenis berarti compiler memvalidasi jenis saat mengompilasi, dan akan menampilkan error jika Anda mencoba menetapkan jenis yang salah ke sebuah variabel.)

Dalam tugas ini, Anda menyiapkan data binding, dan menggunakan data binding untuk mengganti panggilan ke findViewById() dengan panggilan ke objek binding.

Langkah 1: Aktifkan data binding

Untuk menggunakan data binding, Anda harus mengaktifkan data binding di file Gradle, karena data tersebut tidak diaktifkan secara default. Hal ini karena data binding meningkatkan waktu kompilasi dan dapat memengaruhi waktu startup aplikasi.

  1. Jika Anda tidak memiliki aplikasi AboutMe dari codelab sebelumnya, dapatkan kode AboutMeDataBinding-Starter dari GitHub. Buka di Android Studio.
  2. Buka file build.gradle (Module: app).
  3. Di dalam bagian android, sebelum kurung kurawal tutup, tambahkan bagian dataBinding dan tetapkan enabled ke true.
dataBinding {
    enabled = true
}
  1. Saat diminta, Sinkronkan project. Jika tidak diminta, pilih File > Sync Project with Gradle Files.
  2. Anda dapat menjalankan aplikasi, tetapi tidak dapat melihat perubahan apa pun.

Langkah 2: Ubah file tata letak agar dapat digunakan dengan data binding

Untuk bekerja dengan data binding, Anda harus menggabungkan tata letak XML dengan tag <layout>. Hal ini bertujuan agar class root tidak lagi menjadi grup tampilan, melainkan sebagai tata letak yang berisi kelompok tampilan dan tampilan. Objek binding kemudian dapat mengetahui tentang tata letak dan tampilan di dalamnya.

  1. Buka file activity_main.xml.
  2. Beralih ke tab Text.
  3. Tambahkan <layout></layout> sebagai tag terluar di sekitar <LinearLayout>.
<layout>
   <LinearLayout ... >
   ...
   </LinearLayout>
</layout>
  1. Pilih Kode > Format ulang kode untuk memperbaiki indentasi kode.

    Deklarasi ruang nama untuk tata letak harus berada di tag terluar.
  1. Potong deklarasi namespace dari <LinearLayout> dan tempelkan ke tag <layout>. Tag <layout> pembuka harus terlihat seperti di bawah, dan tag <LinearLayout> hanya boleh berisi properti tampilan.
<layout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
  1. Buat dan jalankan aplikasi Anda untuk memverifikasi bahwa Anda telah melakukannya dengan benar.

Langkah 3: Buat objek binding di aktivitas utama

Tambahkan referensi ke objek binding ke aktivitas utama, sehingga Anda dapat menggunakannya untuk mengakses tampilan:

  1. Buka file MainActivity.kt.
  2. Sebelum onCreate(), di tingkat atas, buat variabel untuk objek binding. Variabel ini biasanya disebut binding.

    Jenis binding, class ActivityMainBinding, dibuat oleh compiler khusus untuk aktivitas utama ini. Namanya diambil dari nama file tata letak, yaitu, activity_main + Binding.
private lateinit var binding: ActivityMainBinding
  1. Jika diminta oleh Android Studio, impor ActivityMainBinding. Jika Anda tidak diminta, klik ActivityMainBinding, lalu tekan Alt+Enter (Option+Enter di Mac) untuk mengimpor class yang tidak ada. (Untuk pintasan keyboard lainnya, lihat Pintasan keyboard.)

    Pernyataan import akan terlihat mirip dengan yang ditampilkan di bawah ini.
import com.example.android.aboutme.databinding.ActivityMainBinding

Selanjutnya, ganti fungsi setContentView() saat ini dengan petunjuk yang melakukan hal berikut:

  • Membuat objek binding.
  • Menggunakan fungsi setContentView() dari class DataBindingUtil untuk mengaitkan tata letak activity_main dengan MainActivity. Fungsi setContentView() ini juga menangani beberapa penyiapan data binding untuk tampilan.
  1. Di onCreate(), ganti panggilan setContentView() dengan baris kode berikut.
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
  1. Impor DataBindingUtil.
import androidx.databinding.DataBindingUtil

Langkah 4: Gunakan objek binding untuk mengganti semua panggilan ke findViewById()

Sekarang Anda dapat mengganti semua panggilan ke findViewById() dengan referensi ke tampilan yang ada di objek binding. Saat objek binding dibuat, compiler akan membuat nama tampilan dalam objek binding dari ID tampilan dalam tata letak, dan mengonversinya menjadi camel case. Jadi, misalnya, done_button adalah doneButton dalam objek binding, nickname_edit menjadi nicknameEdit, dan nickname_text menjadi nicknameText.

  1. Di onCreate(), ganti kode yang menggunakan findViewById() untuk menemukan done_button dengan kode yang mereferensikan tombol di objek binding.

    Ganti kode ini: findViewById<Button>(R.id.done_button)
    dengan: binding.doneButton

    Kode yang sudah selesai untuk menetapkan pemroses klik di onCreate() akan terlihat seperti ini.
binding.doneButton.setOnClickListener {
   addNickname(it)
}
  1. Lakukan hal yang sama untuk semua panggilan ke findViewById() dalam fungsi addNickname().
    Ganti semua kemunculan findViewById<View>(R.id.id_view) dengan binding.idView. Lakukan dengan cara berikut:
  • Hapus definisi untuk variabel editText dan nicknameTextView beserta panggilannya ke findViewById(). Tindakan ini akan menampilkan error.
  • Perbaiki error dengan mendapatkan tampilan nicknameText, nicknameEdit, dan doneButton dari objek binding, bukan variabel (yang dihapus).
  • Mengganti view.visibility dengan binding.doneButton.visibility. Menggunakan binding.doneButton alih-alih view yang diteruskan akan membuat kode lebih konsisten.

    Hasilnya adalah kode berikut:
binding.nicknameText.text = binding.nicknameEdit.text
binding.nicknameEdit.visibility = View.GONE
binding.doneButton.visibility = View.GONE
binding.nicknameText.visibility = View.VISIBLE
  • Tidak ada perubahan fungsi. Secara opsional, Anda kini dapat menghilangkan parameter view dan memperbarui semua penggunaan view untuk menggunakan binding.doneButton di dalam fungsi ini.
  1. nicknameText memerlukan String, dan nicknameEdit.text adalah Editable. Saat menggunakan data binding, Editable harus dikonversi secara eksplisit menjadi String.
binding.nicknameText.text = binding.nicknameEdit.text.toString()
  1. Anda dapat menghapus impor yang berwarna abu-abu.
  2. Lakukan Kotlin pada fungsi menggunakan apply{}.
binding.apply {
   nicknameText.text = nicknameEdit.text.toString()
   nicknameEdit.visibility = View.GONE
   doneButton.visibility = View.GONE
   nicknameText.visibility = View.VISIBLE
}
  1. Build dan jalankan aplikasi Anda...yang seharusnya akan terlihat dan berfungsi sama persis seperti sebelumnya.

Anda dapat memanfaatkan data binding agar class data tersedia langsung ke tampilan. Teknik ini menyederhanakan kode, dan sangat berharga untuk menangani kasus yang lebih kompleks.

Untuk contoh ini, Anda membuat class data untuk nama dan nama panggilan, bukan menetapkan nama dan nama panggilan menggunakan resource string. Anda membuat class data tersedia untuk tampilan menggunakan data binding.

Langkah 1: Buat class data MyName

  1. Di Android Studio dalam direktori java, buka file MyName.kt. Jika Anda tidak memiliki file ini, buat file Kotlin baru dan beri nama MyName.kt.
  2. Menentukan class data untuk nama dan nama panggilan. Gunakan string kosong sebagai nilai default.
data class MyName(var name: String = "", var nickname: String = "")

Langkah 2: Tambahkan data ke tata letak

Dalam file activity_main.xml, nama saat ini ditetapkan dalam TextView dari resource string. Anda perlu mengganti referensi dengan nama dengan referensi ke data di class data.

  1. Buka activity_main.xml di tab Text.
  2. Di bagian atas tata letak, di antara tag <layout> dan <LinearLayout>, sisipkan tag <data></data>. Di sinilah Anda akan menghubungkan tampilan dengan data.
<data>
  
</data>

Di dalam tag data, Anda dapat mendeklarasikan variabel bernama yang menyimpan referensi ke class.

  1. Di dalam tag <data>, tambahkan tag <variable>.
  2. Tambahkan parameter name untuk memberi nama variabel "myName". Tambahkan parameter type dan tetapkan jenis ke nama yang sepenuhnya memenuhi syarat dari class data MyName (nama paket + nama variabel).
<variable
       name="myName"
       type="com.example.android.aboutme.MyName" />

Sekarang, Anda dapat mereferensikan variabel myName daripada menggunakan resource string untuk nama tersebut.

  1. Ganti android:text="@string/name" dengan kode di bawah ini.

@={} adalah perintah untuk mendapatkan data yang dirujuk dalam tanda kurung kurawal.

myName merujuk ke variabel myName yang telah Anda tentukan sebelumnya, yang mengarah ke class data myName dan mengambil properti name dari class.

android:text="@={myName.name}"

Langkah 3: Buat data

Sekarang Anda memiliki referensi ke data dalam file tata letak. Selanjutnya, Anda akan membuat data aktual.

  1. Buka file MainActivity.kt.
  2. Di atas onCreate(), buat variabel pribadi, juga disebut myName berdasarkan konvensi. Tetapkan variabel ke instance class data MyName yang meneruskan nama.
private val myName: MyName = MyName("Aleks Haecky")
  1. Di onCreate(), tetapkan nilai variabel myName di file tata letak ke nilai variabel myName yang baru saja Anda deklarasikan. Anda tidak dapat mengakses variabel dalam XML secara langsung. Anda perlu mengaksesnya melalui objek binding.
binding.myName = myName
  1. Tindakan ini mungkin menampilkan error, karena Anda perlu memuat ulang objek binding setelah melakukan perubahan. Build aplikasi Anda, dan error ini akan hilang.

Langkah 4: Gunakan class data untuk nama panggilan di TextView

Langkah terakhir adalah menggunakan class data untuk nama panggilan di TextView.

  1. Buka activity_main.xml.
  2. Pada tampilan teks nickname_text, tambahkan properti text. Lihat nickname di class data, seperti yang ditunjukkan di bawah.
android:text="@={myName.nickname}"
  1. Di ActivityMain, ganti
    nicknameText.text = nicknameEdit.text.toString()
    dengan kode untuk menetapkan nama panggilan dalam variabel myName.
myName?.nickname = nicknameEdit.text.toString()

Setelah nama panggilan ditetapkan, Anda ingin kode memuat ulang UI dengan data baru. Untuk melakukannya, Anda harus membatalkan semua ekspresi binding agar dapat dibuat ulang dengan data yang benar.

  1. Tambahkan invalidateAll() setelah menetapkan nama panggilan sehingga UI dimuat ulang dengan nilai di objek binding yang diperbarui.
binding.apply {
   myName?.nickname = nicknameEdit.text.toString()
   invalidateAll()
   ...
}
  1. Build dan jalankan aplikasi Anda, serta seharusnya akan berfungsi sama persis seperti sebelumnya.

Project Android Studio: AboutMeDataBinding

Langkah-langkah untuk menggunakan data binding untuk mengganti panggilan ke findViewById():

  1. Aktifkan data binding di bagian Android pada file build.gradle:
    dataBinding { enabled = true }
  2. Gunakan <layout> sebagai tampilan root dalam tata letak XML Anda.
  3. Tentukan variabel binding:
    private lateinit var binding: ActivityMainBinding
  4. Buat objek binding di MainActivity, menggantikan setContentView:
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
  5. Mengganti panggilan ke findViewById() dengan referensi ke tampilan di objek binding. Misalnya:
    findViewById<Button>(R.id.done_button) ⇒ binding.doneButton
    (Dalam contoh ini, nama tampilan dihasilkan camel case dari tampilan id dalam XML.)

Langkah-langkah untuk mengikat tampilan ke data:

  1. Buat class data untuk data Anda.
  2. Tambahkan blok <data> di dalam tag <layout>.
  3. Tentukan <variable> dengan nama, dan jenis yang merupakan class data.
<data>
   <variable
       name="myName"
       type="com.example.android.aboutme.MyName" />
</data>
  1. Di MainActivity, buat variabel dengan instance class data. Contoh:
    private val myName: MyName = MyName("Aleks Haecky")
  1. Di objek binding, tetapkan variabel ke variabel yang baru saja Anda buat:
    binding.myName = myName
  1. Pada XML, tetapkan konten tampilan ke variabel yang Anda tentukan dalam blok <data>. Gunakan notasi titik untuk mengakses data di dalam class data.
    android:text="@={myName.name}"

Kursus Udacity:

Dokumentasi developer Android:

Bagian ini mencantumkan kemungkinan tugas pekerjaan rumah untuk siswa yang mengerjakan codelab ini sebagai bagian dari kursus yang dipimpin oleh instruktur. Terserah instruktur untuk melakukan hal berikut:

  • Tugaskan pekerjaan rumah jika diperlukan.
  • Berkomunikasi dengan siswa cara mengirimkan tugas pekerjaan rumah.
  • Beri nilai tugas pekerjaan rumah.

Instruktur dapat menggunakan saran ini sesedikit atau sebanyak yang mereka inginkan, dan harus bebas memberikan pekerjaan rumah lain yang dirasa sesuai.

Jika Anda mengerjakan codelab ini sendiri, silakan gunakan tugas pekerjaan rumah ini untuk menguji pengetahuan Anda.

Jawab pertanyaan berikut

Pertanyaan 1

Mengapa Anda ingin meminimalkan panggilan eksplisit dan implisit ke findViewById()?

  • Setiap kali dipanggil, findViewById() akan melintasi hierarki tampilan.
  • findViewById() berjalan di thread utama atau UI thread.
  • Panggilan ini dapat memperlambat antarmuka pengguna.
  • Aplikasi Anda kemungkinan tidak mengalami error.

Pertanyaan 2

Bagaimana Anda menjelaskan data binding?

Misalnya, berikut adalah beberapa hal yang bisa Anda katakan tentang data binding:

  • Ide besar tentang data binding adalah membuat objek yang menghubungkan/memetakan/mengikat dua informasi jarak jauh secara bersamaan pada waktu kompilasi, sehingga Anda tidak perlu mencari data pada waktu proses.
  • Objek yang menampilkan binding ini kepada Anda disebut objek binding.
  • Objek binding dibuat oleh compiler.

Pertanyaan 3

Manakah dari berikut ini yang BUKAN merupakan manfaat dari data binding?

  • Kode lebih pendek, lebih mudah dibaca, dan lebih mudah dikelola.
  • Data dan tampilan dipisahkan dengan jelas.
  • Sistem Android hanya melintasi hierarki tampilan sekali untuk mendapatkan setiap tampilan.
  • Memanggil findViewById() akan menghasilkan error compiler.
  • Keamanan jenis untuk mengakses tampilan.

Pertanyaan 4

Apa fungsi tag <layout>?

  • Anda menggabungkannya ke tampilan root di tata letak.
  • Binding dibuat untuk semua tampilan dalam tata letak.
  • Cara ini menentukan tampilan tingkat atas dalam tata letak XML yang menggunakan data binding.
  • Anda dapat menggunakan tag <data> di dalam <layout> untuk mengikat variabel ke class data.

Pertanyaan 5

Manakah cara yang benar untuk mereferensikan data terikat dalam tata letak XML?

  • android:text="@={myDataClass.property}"
  • android:text="@={myDataClass}"
  • android:text="@={myDataClass.property.toString()}"
  • android:text="@={myDataClass.bound_data.property}"

Mulai pelajaran berikutnya: 3.1: Membuat fragmen

Untuk link ke codelab lainnya dalam kursus ini, lihat halaman landing codelab Dasar-Dasar Kotlin Android.