Performa Xamarin.Android

Ada banyak teknik untuk meningkatkan performa aplikasi yang dibangun dengan Xamarin.Android. Secara kolektif teknik ini dapat sangat mengurangi jumlah pekerjaan yang dilakukan oleh CPU, dan jumlah memori yang dikonsumsi oleh aplikasi. Artikel ini menjelaskan dan membahas teknik-teknik ini.

Gambaran Umum Performa

Performa aplikasi yang buruk menyajikan dirinya dalam banyak hal. Ini dapat membuat aplikasi tampak tidak responsif, dapat menyebabkan pengguliran lambat, dan dapat mengurangi masa pakai baterai. Namun, mengoptimalkan performa melibatkan lebih dari sekadar menerapkan kode yang efisien. Pengalaman pengguna tentang performa aplikasi juga harus dipertimbangkan. Misalnya, memastikan bahwa operasi dijalankan tanpa memblokir pengguna untuk melakukan aktivitas lain dapat membantu meningkatkan pengalaman pengguna.

Ada sejumlah teknik untuk meningkatkan performa, dan performa yang dirasakan, dari aplikasi yang dibangun dengan Xamarin.Android. Meliputi:

Catatan

Sebelum membaca artikel ini, Anda harus terlebih dahulu membaca Performa Lintas Platform, yang membahas teknik khusus non-platform untuk meningkatkan penggunaan memori dan performa aplikasi yang dibangun menggunakan platform Xamarin.

Optimalkan Hierarki Tata Letak

Setiap tata letak yang ditambahkan ke aplikasi memerlukan inisialisasi, tata letak, dan gambar. Kode tata letak bisa mahal saat menyarangkan LinearLayout instans yang menggunakan weight parameter , karena setiap anak akan diukur dua kali. Menggunakan instans LinearLayout berlapis dapat menyebabkan hierarki tampilan mendalam, yang dapat mengakibatkan performa yang buruk untuk tata letak yang dilambungkan beberapa kali, seperti dalam ListView. Oleh karena itu, penting bahwa tata letak tersebut dioptimalkan, karena manfaat performa kemudian akan dikalikan.

Misalnya, pertimbangkan LinearLayout untuk baris tampilan daftar yang memiliki ikon, judul, dan deskripsi. LinearLayout akan berisi ImageView dan vertikal LinearLayout yang berisi dua TextView instans:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="5dip">
    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_marginRight="5dip"
        android:src="@drawable/icon" />
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="fill_parent">
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:text="Mei tempor iuvaret ad." />
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:singleLine="true"
            android:ellipsize="marquee"
            android:text="Lorem ipsum dolor sit amet." />
    </LinearLayout>
</LinearLayout>

Tata letak ini dalam 3 tingkat, dan boros ketika digembungkan untuk setiap ListView baris. Namun, ini dapat ditingkatkan dengan meratakan tata letak, seperti yang ditunjukkan dalam contoh kode berikut:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="5dip">
    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="5dip"
        android:src="@drawable/icon" />
    <TextView
        android:id="@+id/secondLine"
        android:layout_width="fill_parent"
        android:layout_height="25dip"
        android:layout_toRightOf="@id/icon"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:text="Lorem ipsum dolor sit amet." />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/icon"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_above="@id/secondLine"
        android:layout_alignWithParentIfMissing="true"
        android:gravity="center_vertical"
        android:text="Mei tempor iuvaret ad." />
</RelativeLayout>

Hierarki 3 tingkat sebelumnya telah dikurangi menjadi hierarki 2 tingkat, dan satu RelativeLayout telah menggantikan dua LinearLayout instans. Peningkatan performa yang signifikan akan diperoleh saat menggelembungkan tata letak untuk setiap ListView baris.

Optimalkan Tampilan Daftar

Pengguna mengharapkan pengguliran yang lancar dan waktu pemuatan yang cepat untuk ListView instans. Namun, performa gulir dapat menderita ketika setiap baris tampilan daftar berisi hierarki tampilan berlapis dalam, atau saat baris tampilan daftar berisi tata letak yang kompleks. Namun, ada teknik yang dapat digunakan untuk menghindari performa yang buruk ListView :

  • Gunakan kembali tampilan baris Untuk informasi selengkapnya, lihat Menggunakan Kembali Tampilan Baris.
  • Meratakan tata letak, jika memungkinkan.
  • Konten baris cache yang diambil dari layanan web.
  • Hindari penskalakan gambar.

Secara kolektif teknik ini dapat membantu menjaga agar instans tetap ListView lancar.

Gunakan Kembali Tampilan Baris

Saat menampilkan ratusan baris dalam , ListViewitu akan menjadi pemborosan memori untuk membuat ratusan View objek ketika hanya sejumlah kecil yang ditampilkan di layar sekaligus. Sebaliknya, hanya objek yang View terlihat di baris di layar yang dapat dimuat ke dalam memori, dengan konten yang dimuat ke dalam objek yang digunakan kembali ini. Ini mencegah instansiasi ratusan objek tambahan, menghemat waktu dan memori.

Oleh karena itu, ketika baris menghilang dari layar tampilannya dapat ditempatkan dalam antrean untuk digunakan kembali, seperti yang ditunjukkan dalam contoh kode berikut:

public override View GetView(int position, View convertView, ViewGroup parent)
{
   View view = convertView; // re-use an existing view, if one is supplied
   if (view == null) // otherwise create a new one
       view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
   // set view properties to reflect data for the given row
   view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = items[position];
   // return the view, populated with data, for display
   return view;
}

Saat pengguna menggulir, ListView panggilan penimpaan GetView untuk meminta tampilan baru ditampilkan - jika tersedia, itu melewati tampilan yang tidak digunakan dalam convertView parameter. Jika nilai ini maka null kode membuat instans baru View , jika tidak convertView , properti dapat diatur ulang dan digunakan kembali.

Untuk informasi selengkapnya, lihat Tampilan Baris Yang Digunakan Kembali dalam Mengisi ListView dengan Data.

Menghapus Penanganan Aktivitas dalam Aktivitas

Ketika aktivitas dihancurkan di runtime Android, aktivitas masih dapat hidup di runtime Mono. Oleh karena itu, hapus penanganan aktivitas ke objek Activity.OnPause eksternal untuk mencegah runtime menyimpan referensi ke aktivitas yang telah dihancurkan.

Dalam aktivitas, deklarasikan penanganan aktivitas di tingkat kelas:

EventHandler<UpdatingEventArgs> service1UpdateHandler;

Kemudian terapkan handler dalam aktivitas, seperti di OnResume:

service1UpdateHandler = (object s, UpdatingEventArgs args) => {
    this.RunOnUiThread (() => {
        this.updateStatusText1.Text = args.Message;
    });
};
App.Current.Service1.Updated += service1UpdateHandler;

Ketika aktivitas keluar dari status berjalan, OnPause dipanggil. OnPause Dalam implementasi, hapus handler sebagai berikut:

App.Current.Service1.Updated -= service1UpdateHandler;

Membatasi Masa Pakai Layanan

Saat layanan dimulai, Android menjaga proses layanan tetap berjalan. Ini membuat proses mahal karena memorinya tidak dapat di-paged, atau digunakan di tempat lain. Meninggalkan layanan yang berjalan ketika tidak diperlukan oleh karena itu meningkatkan risiko aplikasi yang menunjukkan performa yang buruk karena kendala memori. Ini juga dapat membuat peralihan aplikasi kurang efisien karena mengurangi jumlah proses yang dapat di-cache Android.

Masa pakai layanan dapat dibatasi dengan menggunakan IntentService, yang mengakhiri dirinya sendiri setelah ditangani niat yang memulainya.

Rilis Sumber Daya saat Diberi Tahu

Selama siklus hidup aplikasi, OnTrimMemory panggilan balik memberikan pemberitahuan ketika memori perangkat rendah. Panggilan balik ini harus diimplementasikan untuk mendengarkan pemberitahuan tingkat memori berikut:

Selain itu, ketika proses aplikasi di-cache, pemberitahuan tingkat memori berikut dapat diterima oleh OnTrimMemory panggilan balik:

  • TrimMemoryBackground – rilis sumber daya yang dapat dibangun kembali dengan cepat dan efisien jika pengguna kembali ke aplikasi.
  • TrimMemoryModerate – melepaskan sumber daya dapat membantu sistem menjaga proses lain tetap di-cache untuk performa keseluruhan yang lebih baik.
  • TrimMemoryComplete – proses aplikasi akan segera dihentikan jika lebih banyak memori tidak segera dipulihkan.

Pemberitahuan harus direspons dengan merilis sumber daya berdasarkan tingkat yang diterima.

Rilis Sumber Daya saat Antarmuka Pengguna Disembunyikan

Rilis sumber daya apa pun yang digunakan oleh antarmuka pengguna aplikasi saat pengguna menavigasi ke aplikasi lain, karena dapat secara signifikan meningkatkan kapasitas Android untuk proses cache, yang pada gilirannya dapat berdampak pada kualitas pengalaman pengguna.

Untuk menerima pemberitahuan saat pengguna keluar dari UI, terapkan OnTrimMemory panggilan balik di Activity kelas dan dengarkan TrimMemoryUiHidden tingkat, yang menunjukkan bahwa UI disembunyikan dari tampilan. Pemberitahuan ini hanya akan diterima ketika semua komponen UI aplikasi disembunyikan dari pengguna. Merilis sumber daya UI saat pemberitahuan ini diterima memastikan bahwa jika pengguna menavigasi kembali dari aktivitas lain di aplikasi, sumber daya UI masih tersedia untuk melanjutkan aktivitas dengan cepat.

Optimalkan Sumber Daya Gambar

Gambar adalah beberapa sumber daya termahal yang digunakan aplikasi, dan sering ditangkap pada resolusi tinggi. Oleh karena itu, saat menampilkan gambar, tampilkan pada resolusi yang diperlukan untuk layar perangkat. Jika gambar memiliki resolusi yang lebih tinggi dari layar, gambar harus diturunkan skalanya.

Untuk informasi selengkapnya, lihat Mengoptimalkan Sumber Daya Gambar di panduan Performa Lintas Platform.

Buang Sumber Daya Gambar yang Tidak Digunakan

Untuk menghemat penggunaan memori, ada baiknya untuk membuang sumber daya gambar besar yang tidak lagi diperlukan. Namun, penting untuk memastikan bahwa gambar dibuang dengan benar. Alih-alih menggunakan pemanggilan eksplisit .Dispose() , Anda dapat memanfaatkan penggunaan pernyataan untuk memastikan penggunaan IDisposable objek yang benar.

Misalnya, kelas Bitmap mengimplementasikan IDisposable. Membungkus instansiasi BitMap objek dalam using blok memastikan bahwa objek akan dibuang dengan benar saat keluar dari blok:

using (Bitmap smallPic = BitmapFactory.DecodeByteArray(smallImageByte, 0, smallImageByte.Length))
{
    // Use the smallPic bit map here
}

Untuk informasi selengkapnya tentang merilis sumber daya sekali pakai, lihat Merilis Sumber Daya IDisposable.

Hindari Aritmatika Titik Mengambang

Pada perangkat Android, aritmatika floating-point sekitar 2x lebih lambat dari aritmatika bilangan bulat. Oleh karena itu, ganti aritmatika floating-point dengan aritmatika bilangan bulat jika memungkinkan. Namun, tidak ada perbedaan waktu eksekusi antara float dan double aritmatika pada perangkat keras baru-baru ini.

Catatan

Bahkan untuk aritmatika bilangan bulat, beberapa CPU tidak memiliki kemampuan pembagian perangkat keras. Oleh karena itu, pembagian bilangan bulat dan operasi modulus sering dilakukan dalam perangkat lunak.

Menutup Dialog

Saat menggunakan ProgressDialog kelas (atau dialog atau pemberitahuan apa pun), alih-alih memanggil Hide metode ketika tujuan dialog selesai, panggil Dismiss metode . Jika tidak, dialog akan tetap hidup dan akan membocorkan aktivitas dengan memegang referensi ke dalamnya.

Ringkasan

Artikel ini menjelaskan dan membahas teknik untuk meningkatkan performa aplikasi yang dibangun dengan Xamarin.Android. Secara kolektif teknik ini dapat sangat mengurangi jumlah pekerjaan yang dilakukan oleh CPU, dan jumlah memori yang dikonsumsi oleh aplikasi.