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

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

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

Untuk menyetel data dalam tampilan, Anda telah menggunakan resource string dan menyetel data dari aktivitas. Akan lebih efisien jika tampilan mengetahui data. Dan untungnya, hal ini dapat 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

  • Ubah aplikasi untuk menggunakan data binding, bukan findViewById(), dan 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 persis sama 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. Kolom dan tombol yang dapat diedit diganti dengan tampilan teks yang menampilkan nama panggilan yang dimasukkan.


Anda dapat menggunakan kode yang Anda buat 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 menjelajahi hierarki tampilan saat runtime untuk menemukannya. Jika aplikasi Anda hanya memiliki beberapa tampilan, hal ini tidak menjadi masalah. Namun, aplikasi produksi mungkin memiliki puluhan tampilan dalam tata letak, dan meskipun dengan desain terbaik, akan ada tampilan bertingkat.

Bayangkan tata letak linear yang berisi scroll view yang berisi tampilan teks. Untuk hierarki tampilan yang besar atau dalam, menemukan tampilan dapat memakan waktu yang cukup lama sehingga dapat memperlambat aplikasi secara signifikan bagi pengguna. Menge-cache tampilan dalam variabel dapat membantu, tetapi Anda tetap harus menginisialisasi variabel untuk setiap tampilan, di setiap namespace. Dengan banyaknya tampilan dan beberapa aktivitas, hal ini juga akan menambah penggunaan data.

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 pengikatan dibuat untuk aplikasi Anda, Anda dapat mengakses tampilan, dan data lainnya, melalui objek pengikatan, tanpa harus melintasi 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 data binding ini akan menjadi semakin penting di bagian selanjutnya dalam kursus ini.
  • Sistem Android hanya melintasi hierarki tampilan satu kali untuk mendapatkan setiap tampilan, dan hal ini terjadi selama startup aplikasi, bukan saat runtime ketika pengguna berinteraksi dengan aplikasi.
  • Anda mendapatkan keamanan jenis untuk mengakses tampilan. (Type safety berarti compiler memvalidasi jenis saat mengompilasi, dan akan menampilkan error jika Anda mencoba menetapkan jenis yang salah ke sebuah variabel.)

Dalam tugas ini, Anda akan 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 perlu mengaktifkan data binding di file Gradle, karena data binding tidak diaktifkan secara default. Hal ini karena data binding meningkatkan waktu kompilasi dan dapat memengaruhi waktu peluncuran 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 penutup, tambahkan bagian dataBinding dan tetapkan enabled ke true.
dataBinding {
    enabled = true
}
  1. Saat diminta, Sinkronkan project. Jika Anda tidak diminta, pilih File > Sync Project with Gradle Files.
  2. Anda dapat menjalankan aplikasi, tetapi tidak akan melihat perubahan apa pun.

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

Untuk menggunakan binding data, Anda harus membungkus tata letak XML dengan tag <layout>. Hal ini dilakukan agar class root tidak lagi menjadi grup tampilan, tetapi menjadi tata letak yang berisi grup tampilan dan tampilan. Objek binding kemudian dapat mengetahui tata letak dan tampilan di dalamnya.

  1. Buka file activity_main.xml.
  2. Beralihlah ke tab Teks.
  3. Tambahkan <layout></layout> sebagai tag terluar di sekitar <LinearLayout>.
<layout>
   <LinearLayout ... >
   ...
   </LinearLayout>
</layout>
  1. Pilih Code > Reformat code untuk memperbaiki indentasi kode.

    Pernyataan namespace untuk tata letak harus berada di tag terluar.
  1. Potong deklarasi namespace dari <LinearLayout> dan tempelkan ke tag <layout>. Tag <layout> pembuka Anda akan terlihat seperti yang ditunjukkan 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. Bangun dan jalankan aplikasi Anda untuk memverifikasi bahwa Anda melakukannya dengan benar.

Langkah 3: Buat objek pengikatan 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 level teratas, buat variabel untuk objek binding. Variabel ini biasanya disebut binding.

    Jenis binding, class ActivityMainBinding, dibuat oleh compiler khusus untuk aktivitas utama ini. Nama ini berasal 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 dan tekan Alt+Enter (Option+Enter di Mac) untuk mengimpor class yang tidak ada ini. (Untuk pintasan keyboard lainnya, lihat Pintasan keyboard.)

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

Selanjutnya, Anda mengganti 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 pengikatan data 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 di objek binding dari ID tampilan dalam tata letak, lalu 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 dalam objek binding.

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

    Kode yang sudah selesai untuk menyetel 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(). Hal ini akan menyebabkan error.
  • Perbaiki error dengan mendapatkan tampilan nicknameText, nicknameEdit, dan doneButton dari objek binding, bukan dari variabel (yang dihapus).
  • Ganti view.visibility dengan binding.doneButton.visibility. Penggunaan binding.doneButton, bukan view yang diteruskan, 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 sekarang 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 binding data, Anda harus mengonversi Editable secara eksplisit ke String.
binding.nicknameText.text = binding.nicknameEdit.text.toString()
  1. Anda dapat menghapus impor yang berwarna abu-abu.
  2. Ubah fungsi menjadi Kotlin dengan menggunakan apply{}.
binding.apply {
   nicknameText.text = nicknameEdit.text.toString()
   nicknameEdit.visibility = View.GONE
   doneButton.visibility = View.GONE
   nicknameText.visibility = View.VISIBLE
}
  1. Buat dan jalankan aplikasi Anda...dan aplikasi akan terlihat dan berfungsi persis sama seperti sebelumnya.

Anda dapat memanfaatkan data binding untuk membuat class data tersedia langsung untuk tampilan. Teknik ini menyederhanakan kode, dan sangat berguna untuk menangani kasus yang lebih rumit.

Untuk contoh ini, alih-alih menyetel nama dan nama panggilan menggunakan resource string, Anda membuat class data untuk nama dan nama panggilan. Anda membuat class data tersedia untuk tampilan menggunakan data binding.

Langkah 1: Buat class data MyName

  1. Di Android Studio di direktori java, buka file MyName.kt. Jika Anda tidak memiliki file ini, buat file Kotlin baru dan beri nama MyName.kt.
  2. Tentukan 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 ke nama dengan referensi ke data di class data.

  1. Buka activity_main.xml di tab Text.
  2. Di bagian atas tata letak, 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 variabel nama "myName". Tambahkan parameter type dan tetapkan jenisnya ke nama yang sepenuhnya memenuhi syarat dari class data MyName (nama paket + nama variabel).
<variable
       name="myName"
       type="com.example.android.aboutme.MyName" />

Sekarang, alih-alih menggunakan resource string untuk nama, Anda dapat mereferensikan variabel myName.

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

@={} adalah direktif untuk mendapatkan data yang direferensikan di dalam tanda kurung kurawal.

myName mereferensikan variabel myName yang sebelumnya Anda tentukan, 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 membuat data sebenarnya.

  1. Buka file MainActivity.kt.
  2. Di atas onCreate(), buat variabel pribadi, yang juga disebut myName berdasarkan konvensi. Tetapkan instance class data MyName ke variabel, dengan meneruskan nama.
private val myName: MyName = MyName("Aleks Haecky")
  1. Di onCreate(), tetapkan nilai variabel myName dalam file tata letak ke nilai variabel myName yang baru saja Anda deklarasikan. Anda tidak dapat mengakses variabel di XML secara langsung. Anda harus mengaksesnya melalui objek pengikatan.
binding.myName = myName
  1. Hal ini dapat menampilkan error, karena Anda perlu memuat ulang objek binding setelah melakukan perubahan. Bangun aplikasi Anda, dan error 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. Di tampilan teks nickname_text, tambahkan properti text. Referensi 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 di variabel myName.
myName?.nickname = nicknameEdit.text.toString()

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

  1. Tambahkan invalidateAll() setelah menyetel nama panggilan agar UI dimuat ulang dengan nilai dalam objek binding yang diperbarui.
binding.apply {
   myName?.nickname = nicknameEdit.text.toString()
   invalidateAll()
   ...
}
  1. Bangun dan jalankan aplikasi Anda, dan aplikasi akan berfungsi persis sama seperti sebelumnya.

Project Android Studio: AboutMeDataBinding

Langkah-langkah 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. Ganti panggilan ke findViewById() dengan referensi ke tampilan di objek binding. Misalnya: Tombol
    findViewById<Button>(R.id.done_button) ⇒ binding.doneBu
    (Dalam contoh, nama tampilan dibuat camel case dari id tampilan di 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. Dalam XML, tetapkan konten tampilan ke variabel yang Anda tentukan di 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. 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

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 mendeskripsikan pengikatan data?

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

  • Ide besar tentang pengikatan data adalah membuat objek yang menghubungkan/memetakan/mengikat dua informasi yang berjauhan bersama-sama pada waktu kompilasi, sehingga Anda tidak perlu mencari data pada waktu runtime.
  • 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 pengikatan data?

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

Pertanyaan 4

Apa fungsi tag <layout>?

  • Anda membungkusnya di sekitar tampilan root dalam tata letak.
  • Binding dibuat untuk semua tampilan dalam tata letak.
  • Menetapkan tampilan tingkat teratas 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 lain dalam kursus ini, lihat halaman landing codelab Dasar-Dasar Android Kotlin.