Performa dan hierarki tampilan

Cara mengelola hierarki objek View dapat berdampak besar pada performa aplikasi Anda. Halaman ini menjelaskan cara menilai apakah hierarki tampilan memperlambat aplikasi Anda, dan menawarkan beberapa strategi untuk mengatasi masalah yang mungkin terjadi.

Performa tata letak dan pengukuran

Pipeline rendering meliputi tahap tata letak dan pengukuran, saat sistem memosisikan item yang relevan dalam hierarki tampilan Anda secara tepat. 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. Biaya tersebut juga dapat lebih tinggi jika objek View perlu mempertimbangkan perubahan ukuran agar sesuai dengan batasannya: Misalnya, jika aplikasi Anda memanggil SetText() pada objek View yang menggabungkan teks, View mungkin perlu diubah ukurannya.

Jika hal ini memakan waktu terlalu lama, proses ini dapat mencegah frame melakukan proses rendering dalam 16 milidetik yang diperbolehkan, sehingga frame akan turun, dan animasi mengalami jank.

Karena Anda tidak dapat memindahkan operasi ini ke thread pekerja, aplikasi Anda harus memprosesnya di thread utama. Langkah terbaiknya adalah dengan mengoptimalkannya agar menghemat waktu kerja seefektif mungkin.

Mengelola kompleksitas: masalah tata letak

Tata letak Android memungkinkan Anda menyarangkan objek UI di hierarki tampilan. Penyarangan (nesting) ini juga dapat menimbulkan biaya tata letak. Jika aplikasi Anda memproses objek untuk tata letak, aplikasi tersebut akan 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.

Kasus paling umum saat tata letak memerlukan waktu yang sangat lama adalah ketika hierarki objek View disusun bertingkat 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.

Jika Anda menggunakan class RelativeLayout, Anda mungkin dapat mencapai efek yang sama, dengan biaya yang lebih rendah, menggunakan tampilan LinearLayout bertingkat dan tidak tertimbang. Selain itu, jika aplikasi Anda menargetkan Android 7.0 (API level 24), kemungkinan Anda dapat menggunakan editor tata letak khusus untuk membuat objek ConstraintLayout, bukan RelativeLayout. Hal tersebut memungkinkan Anda untuk menghindari berbagai masalah yang dijelaskan di bagian ini. Class ConstraintLayout menawarkan kontrol tata letak yang serupa, tetapi dengan performa yang jauh lebih baik. Class ini menggunakan sistem penyelesaian kendala sendiri untuk mengatasi hubungan antara tampilan dengan cara yang sangat berbeda dari tata letak standar.

Taksasi ganda

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

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

  1. Mengeksekusi pass pengukuran dan tata letak, 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 pass tata letak kedua untuk menyelesaikan posisi objek.
  4. Melanjutkan ke tahap selanjutnya dari proses rendering.

Semakin banyak level yang dimiliki hierarki tampilan Anda, semakin besar kemungkinan penalti performanya.

Penampung selain RelativeLayout juga dapat meningkatkan taksasi ganda. Contoh:

  • Tampilan LinearLayout dapat menghasilkan penerusan pengukuran dan tata letak ganda jika dibuat horizontal. Penerusan pengukuran dan tata letak 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 memiliki masalah yang serupa. Penampung ini juga memungkinkan pemosisian relatif, yang normalnya akan 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 pengukuran dan tata letak tidak menjadi beban performa dengan sendirinya. Namun, penerusan ini dapat menjadi beban performa jika berada di tempat yang salah. Anda harus waspada terhadap situasi ketika 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. Ada beberapa fitur yang dapat memberi Anda indikasi kuat tentang lokasi kemunculan bottleneck performa. Beberapa fitur lain memberikan informasi yang kurang pasti, tetapi juga dapat memberikan petunjuk yang berguna.

Systrace

Salah satu alat yang menyediakan data terbaik terkait performa adalah Systrace yang terdapat dalam Android SDK. Alat Systrace memungkinkan Anda mengumpulkan dan memeriksa informasi waktu di seluruh perangkat Android, sehingga Anda dapat mengetahui ketika masalah performa tata letak menyebabkan masalah performa. Untuk informasi selengkapnya tentang Systrace, lihat ringkasan pelacakan sistem.

Rendering GPU profil

Alat lain yang paling mungkin memberi Anda informasi konkret tentang bottleneck performa adalah alat Rendering GPU profil di perangkat, yang tersedia di perangkat yang didukung oleh Android 6.0 (API level 23) dan yang lebih baru. Alat ini memungkinkan Anda melihat berapa lama waktu yang dibutuhkan oleh tahap pengukuran dan tata-letak untuk setiap frame rendering. Data ini dapat membantu Anda mendiagnosis masalah performa runtime, dan membantu Anda menentukan apakah ada masalah tata letak dan ukuran 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 Panduan 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. Menemukan Inspect Code di Android Studio.

Informasi tentang berbagai item tata letak muncul di Android > Lint > Performance. Untuk melihat detail selengkapnya, Anda dapat mengklik masing-masing item untuk memperluasnya dan melihat informasi lebih lanjut dalam panel di sebelah kanan layar. Gambar 2 menunjukkan contoh tampilan tersebut.

Gambar 2. Melihat informasi tentang masalah spesifik yang telah diidentifikasi alat lint.

Mengklik salah satu item ini akan membuka 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, memberikan representasi visual yang jelas dari rantai induk tampilan tertentu, dan 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 memberikan cara mudah bagi Anda untuk mengidentifikasi rantai tata letak bertingkat yang mendalam, atau area tata letak dengan jumlah turunan bertingkat yang banyak, yang merupakan potensi sumber biaya performa yang lain. Dalam skenario ini, tahap pengukuran dan tata letak- bisa menjadi sangat mahal sehingga menyebabkan masalah performa.

Untuk informasi selengkapnya, lihat Men-debug tata letak Anda dengan layout inspector.

Menyelesaikan masalah hierarki tampilan

Konsep dasar di balik penyelesaian masalah performa yang muncul dari hierarki tampilan merupakan konsep yang sederhana, tetapi lebih sulit dalam praktiknya. Mencegah hierarki tampilan agar tidak menerapkan penalti performa mencakup tujuan ganda yaitu meratakan hierarki tampilan Anda dan mengurangi taksasi ganda. Bagian ini membahas beberapa strategi untuk mencapai tujuan tersebut.

Menghapus tata letak bertingkat yang redundan

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 ini menyebabkan redundansi, dan menambah biaya yang tidak perlu ke hierarki tampilan.

Lint sering kali dapat menandai masalah ini untuk Anda, sehingga akan mengurangi waktu debugging.

Mengadopsi merge/include

Salah satu 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>

Kemudian tag include ditambahkan ke item ini pada 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 ini sebenarnya tidak perlu menyusun bertingkat tata letak pertama dalam tata letak kedua.

Tag merge dapat membantu mencegah masalah ini. Untuk informasi tentang tag ini, lihat Menggunakan kembali tata letak dengan <include>.

Menggunakan 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 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 posisional. Dalam rilis N Android, class ConstraintLayout menyediakan fungsi yang mirip dengan RelativeLayout, tetapi dengan biaya yang jauh lebih rendah.