Performa dan hierarki tampilan

Cara mengelola hierarki objek View dapat memengaruhi performa aplikasi Anda secara signifikan. Halaman ini menjelaskan cara menilai apakah hierarki tampilan memperlambat aplikasi Anda atau tidak, dan menawarkan beberapa strategi untuk mengatasi masalah yang mungkin terjadi.

Halaman ini berfokus pada peningkatan tata letak berbasis View. Untuk mengetahui informasi tentang cara meningkatkan performa Jetpack Compose, lihat performa Jetpack Compose.

Performa tata letak dan pengukuran

Pipeline rendering meliputi tahap tata letak dan pengukuran, di mana sistem secara tepat memosisikan item yang relevan dalam hierarki tampilan Anda. Bagian pengukuran pada tahap ini menentukan ukuran dan batas objek View. Bagian tata letak menentukan posisi objek View di layar.

Kedua tahap pipeline ini menimbulkan sedikit biaya per tampilan atau tata letak yang diproses. Biasanya, biaya ini tidak besar dan tidak terlalu memengaruhi performa. Namun, lebih baik lagi jika aplikasi menambahkan atau menghapus objek View, seperti saat objek RecyclerView mendaur ulang atau menggunakannya kembali. Biayanya juga dapat lebih tinggi jika objek View perlu mempertimbangkan pengubahan ukuran agar dapat memenuhi batasannya. Misalnya, jika aplikasi Anda memanggil SetText() pada objek View yang menggabungkan teks, View mungkin perlu diubah ukurannya.

Jika memakan waktu terlalu lama, proses ini dapat mencegah frame melakukan rendering dalam 16 milidetik yang diizinkan, yang dapat membuat frame turun dan membuat animasi menjadi tersendat.

Karena Anda tidak dapat memindahkan operasi ini ke thread pekerja, aplikasi Anda harus memprosesnya di thread utama. Sebaiknya optimalkan operasi tersebut agar menghemat waktu.

Mengelola tata letak yang kompleks

Tata Letak Android memungkinkan Anda menyusun bertingkat objek UI dalam hierarki tampilan. Penyusunan bertingkat (nesting) ini juga dapat menimbulkan biaya tata letak. Saat aplikasi Anda memproses objek untuk tata letak, aplikasi juga melakukan proses yang sama pada semua turunan tata letak.

Untuk tata letak yang rumit, terkadang biaya hanya timbul saat sistem menghitung tata letak untuk pertama kali. Misalnya, saat aplikasi Anda mendaur ulang item daftar yang kompleks dalam objek RecyclerView, sistem tersebut perlu membuat tata letak semua objek tersebut. Dalam contoh lain, perubahan trivial dapat menyebarkan rantai ke arah induk sampai mencapai objek yang tidak memengaruhi ukuran induk.

Alasan umum tata letak memerlukan waktu yang lama adalah saat hierarki objek View disusun bertingkat dengan satu sama lain. Setiap objek tata letak bertingkat menambahkan biaya ke tahapan tata letak. Makin datar hierarki Anda, makin sedikit waktu yang dibutuhkan untuk menyelesaikan tahapan tata letak.

Sebaiknya gunakan Layout Editor untuk membuat ConstraintLayout, bukan RelativeLayout atau LinearLayout, karena umumnya lebih efisien dan mengurangi penyusunan bertingkat tata letak. Namun, untuk tata letak sederhana yang dapat dicapai menggunakan FrameLayout, sebaiknya gunakan FrameLayout.

Jika Anda menggunakan class RelativeLayout, Anda mungkin dapat mencapai efek yang sama, dengan biaya yang lebih rendah, menggunakan tampilan LinearLayout yang bertingkat dan tidak tertimbang. Namun, jika Anda menggunakan tampilan LinearLayout bertingkat dan berbobot, biaya tata letak jauh lebih tinggi karena memerlukan beberapa penerusan tata letak, seperti yang dijelaskan di bagian berikutnya.

Sebaiknya, gunakan juga RecyclerView, bukan ListView, karena dapat mendaur ulang tata letak item daftar individu, yang keduanya lebih efisien dan dapat meningkatkan performa scroll.

Taksasi ganda

Biasanya, framework akan menjalankan tahap tata letak atau pengukuran dalam satu penerusan. Namun, dalam beberapa kasus tata letak yang rumit, framework mungkin harus melakukan iterasi beberapa kali pada bagian hierarki yang memerlukan beberapa penerusan untuk di-resolve sebelum akhirnya menempatkan elemen. Keharusan untuk melakukan lebih dari satu iterasi tata letak dan pengukuran disebut sebagai taksasi ganda.

Misalnya, saat Anda menggunakan penampung RelativeLayout, yang memungkinkan Anda memosisikan objek View sehubungan dengan posisi objek View yang lain, framework akan menjalankan urutan berikut:

  1. Mengeksekusi penerusan tata letak dan pengukuran, di mana framework akan menghitung setiap posisi dan ukuran objek turunan sesuai dengan permintaan setiap turunan.
  2. Menggunakan data ini, yang juga mempertimbangkan bobot objek, untuk mengetahui posisi yang tepat dari tampilan terkait.
  3. Melakukan penerusan tata letak kedua untuk menyelesaikan posisi objek.
  4. Berpindah ke tahap selanjutnya dari proses rendering.

Makin banyak level yang dimiliki hierarki tampilan Anda, makin besar kemungkinan penalti performanya.

Seperti yang disebutkan sebelumnya, ConstraintLayout umumnya lebih efisien daripada tata letak lain, kecuali FrameLayout. Fungsi ini tidak terlalu rentan terhadap beberapa penerusan tata letak, dan dalam banyak kasus, menghilangkan kebutuhan untuk menyusun bertingkat tata letak.

Penampung selain RelativeLayout juga dapat meningkatkan taksasi ganda. Contoh:

  • Tampilan LinearLayout dapat menghasilkan penerusan tata letak dan pengukuran ganda jika dibuat horizontal. Penerusan tata letak dan pengukuran ganda juga dapat terjadi pada orientasi vertikal jika Anda menambahkan measureWithLargestChild, yang dalam hal ini framework mungkin perlu melakukan penerusan kedua untuk me-resolve ukuran objek yang tepat.
  • GridLayout juga memungkinkan pemosisian relatif, tetapi biasanya menghindari taksasi ganda dengan memproses terlebih dahulu hubungan posisi di antara tampilan turunan. Namun, jika tata letak menggunakan bobot atau mengisinya dengan class Gravity, manfaat pemrosesan tersebut akan hilang, sehingga framework mungkin harus melakukan beberapa penerusan jika penampungnya adalah RelativeLayout.

Beberapa penerusan tata letak dan pengukuran tidak selalu membebani performa. Namun, penerusan tersebut dapat menjadi beban jika berada di tempat yang salah. Berhati-hatilah jika salah satu kondisi berikut berlaku pada penampung Anda:

  • Merupakan elemen root dalam hierarki tampilan Anda.
  • Memiliki hierarki tampilan yang mendalam di bawahnya.
  • Ada banyak instance yang mengisi layar, mirip dengan turunan dalam objek ListView.

Mendiagnosis masalah hierarki tampilan

Performa tata letak merupakan masalah yang kompleks dengan banyak faset. Alat berikut dapat membantu Anda mengidentifikasi lokasi terjadinya bottleneck performa. Beberapa alat memberikan informasi yang kurang pasti, tetapi dapat memberikan petunjuk yang bermanfaat.

Perfetto

Perfetto adalah alat yang menyediakan data tentang performa. Anda dapat membuka rekaman aktivitas Android di UI Perfetto.

Rendering GPU profil

Alat rendering GPU Profil di perangkat, yang tersedia di perangkat yang didukung oleh Android 6.0 (level API 23) dan yang lebih baru, dapat memberi informasi konkret tentang bottleneck performa. Alat ini memungkinkan Anda melihat berapa lama waktu yang dibutuhkan oleh tahap tata letak dan pengukuran untuk setiap frame rendering. Data ini dapat membantu Anda mendiagnosis masalah performa runtime dan membantu Anda menentukan apakah ada masalah tata letak dan pengukuran yang perlu Anda atasi.

Dalam representasi grafis data yang ditangkapnya, rendering GPU Profil menggunakan warna biru untuk menggambarkan waktu pembuatan tata letak. Untuk informasi selengkapnya tentang cara menggunakan alat ini, lihat kecepatan rendering GPU Profil.

Lint

Alat Lint Android Studio dapat membantu Anda mendeteksi inefisiensi dalam hierarki tampilan. Untuk menggunakan alat ini, pilih Analyze > Inspect Code, seperti yang ditunjukkan pada gambar 1.

Gambar 1. Pilih Inspect Code di Android Studio.

Informasi tentang berbagai item tata letak muncul di Android > Lint > Performance. Untuk melihat detail selengkapnya, klik setiap item untuk meluaskannya dan menampilkan informasi selengkapnya di panel yang berada di sisi kanan layar. Gambar 2 menunjukkan contoh informasi yang diperluas.

Gambar 2. Menampilkan informasi tentang masalah spesifik yang diidentifikasi alat Lint.

Mengklik item akan memunculkan masalah yang terkait dengan item tersebut di panel sebelah kanan.

Untuk memahami topik dan masalah spesifik di bidang ini lebih lanjut, lihat dokumentasi Lint.

Layout Inspector

Alat Layout Inspector Android Studio memberikan representasi visual dari hierarki tampilan aplikasi Anda. Ini adalah cara yang baik untuk menavigasi hierarki aplikasi Anda, dengan representasi visual yang jelas dari rantai induk tampilan tertentu. Selain itu, alat ini memungkinkan Anda memeriksa tata letak yang dibuat oleh aplikasi Anda.

Tampilan yang disajikan oleh Layout Inspector juga dapat membantu mengidentifikasi masalah performa yang timbul dari taksasi ganda. Ini juga dapat memberi Anda cara untuk mengidentifikasi rantai tata letak bertingkat yang mendalam, atau area tata letak dengan jumlah turunan bertingkat yang banyak, yang dapat menjadi sumber biaya performa. Dalam hal ini, tahap tata letak dan pengukuran dapat membutuhkan biaya yang mahal dan mengakibatkan masalah performa.

Untuk mengetahui informasi selengkapnya, lihat Men-debug tata letak dengan Layout Inspector dan Layout Validation.

Menyelesaikan masalah hierarki tampilan

Konsep dasar di balik penyelesaian masalah performa yang muncul dari hierarki tampilan bisa menjadi sulit dalam praktiknya. Mencegah hierarki tampilan menerapkan penalti performa terdiri dari proses meratakan hierarki tampilan dan mengurangi taksasi ganda. Bagian ini membahas beberapa strategi untuk mencapai tujuan ini.

Menghapus tata letak bersarang yang redundan

ConstraintLayout adalah library Jetpack dengan beragam mekanisme dalam jumlah besar untuk memosisikan tampilan dalam tata letak. Tindakan ini akan mengurangi kebutuhan untuk menyusun bertingkat satu ConstaintLayout dan dapat membantu meratakan hierarki tampilan. Biasanya lebih mudah untuk meratakan hierarki menggunakan ConstraintLayout dibandingkan dengan jenis tata letak lainnya.

Developer sering kali menggunakan tata letak bertingkat lebih dari yang diperlukan. Misalnya, penampung RelativeLayout mungkin berisi satu turunan yang juga berupa penampung RelativeLayout. Susunan bertingkat menyebabkan redundansi dan menambah biaya yang tidak perlu ke hierarki tampilan. Lint dapat menandai masalah ini untuk Anda, sehingga akan mengurangi waktu debugging.

Mengadopsi merge atau include

Penyebab seringnya terjadi tata letak bertingkat yang redundan adalah tag <include>. Misalnya, Anda dapat menentukan tata letak yang bisa digunakan lagi seperti berikut:

<LinearLayout>
    <!-- some stuff here -->
</LinearLayout>

Selanjutnya, Anda dapat menambahkan tag <include> untuk menambahkan item berikut ke penampung induk:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/app_bg"
    android:gravity="center_horizontal">

    <include layout="@layout/titlebar"/>

    <TextView android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:text="@string/hello"
              android:padding="10dp" />

    ...

</LinearLayout>

Include sebelumnya ini sebenarnya tidak perlu menyusun bertingkat tata letak pertama dalam tata letak kedua.

Tag <merge> dapat membantu mencegah masalah ini. Untuk mengetahui informasi tentang tag ini, lihat Menggunakan tag <merge>.

Mengadopsi tata letak yang lebih murah

Anda mungkin tidak dapat menyesuaikan skema tata letak yang ada agar tidak berisi tata letak redundan. Dalam kasus tertentu, satu-satunya solusi yang mungkin adalah meratakan hierarki Anda dengan beralih ke jenis tata letak yang sama sekali berbeda.

Misalnya, Anda mungkin menemukan bahwa TableLayout menyediakan fungsi yang sama dengan tata letak yang lebih kompleks dengan banyak dependensi posisi. Library Jetpack ConstraintLayout menyediakan fungsi yang mirip dengan RelativeLayout, ditambah fitur lainnya untuk membantu membuat tata letak yang lebih datar dan efisien.