Ringkasan proses dan thread

Saat komponen aplikasi dimulai dan tidak ada komponen aplikasi lain yang berjalan, sistem Android akan memulai proses Linux baru untuk aplikasi dengan satu thread eksekusi. Secara default, semua komponen aplikasi yang sama berjalan dalam proses dan thread yang sama, disebut thread utama.

Jika komponen aplikasi dimulai dan sudah ada proses untuk aplikasi tersebut, karena komponen lain dari aplikasi sudah dimulai, komponen akan dimulai dalam proses tersebut dan menggunakan thread eksekusi yang sama. Namun, Anda dapat mengatur berbagai komponen dalam aplikasi agar berjalan dalam proses terpisah, dan Anda dapat membuat thread tambahan untuk setiap proses.

Dokumen ini membahas cara kerja proses dan thread di aplikasi Android.

Proses

Secara default, semua komponen aplikasi berjalan dalam proses yang sama, dan sebagian besar aplikasi tidak mengubahnya. Akan tetapi, jika merasa perlu mengontrol proses mana yang memiliki komponen tertentu, Anda dapat melakukannya di file manifes.

Entri manifes untuk setiap jenis elemen komponen—<activity>, <service>, <receiver>, dan <provider>—mendukung atribut android:process yang dapat menentukan proses yang dijalankan komponen tersebut. Anda dapat menetapkan atribut ini agar setiap komponen berjalan dalam prosesnya sendiri atau agar beberapa komponen menggunakan proses yang sama sementara yang lainnya tidak.

Anda juga dapat menetapkan android:process agar komponen aplikasi yang berbeda berjalan dalam proses yang sama, asalkan aplikasi tersebut menggunakan ID pengguna Linux yang sama dan ditandatangani dengan sertifikat yang sama.

Elemen <application> juga mendukung atribut android:process, yang dapat Anda gunakan untuk menetapkan nilai default yang berlaku untuk semua komponen.

Android mungkin memutuskan untuk menghentikan proses pada waktu tertentu, saat resource diperlukan oleh proses lain yang lebih cepat melayani pengguna. Komponen aplikasi yang berjalan dalam proses yang dinonaktifkan oleh karena itu juga akan dihancurkan. Proses dimulai kembali untuk komponen tersebut ketika ada pekerjaan untuk mereka lakukan.

Saat menentukan proses yang akan dinonaktifkan, sistem Android akan mempertimbangkan kepentingan relatifnya bagi pengguna. Misalnya, tindakan ini lebih mudah menghentikan proses yang menghosting aktivitas yang tidak lagi terlihat di layar, dibandingkan dengan proses yang menghosting aktivitas yang terlihat. Oleh karena itu, keputusan untuk menghentikan proses bergantung pada status komponen yang berjalan dalam proses tersebut.

Detail siklus proses proses dan hubungannya dengan status aplikasi dibahas dalam Proses dan siklus proses aplikasi.

Threads

Saat aplikasi diluncurkan, sistem akan membuat thread eksekusi untuk aplikasi tersebut, yang disebut thread utama. Thread ini sangat penting karena bertugas mengirim peristiwa ke widget antarmuka pengguna yang sesuai, termasuk peristiwa menggambar. Ini juga hampir selalu merupakan thread tempat aplikasi Anda berinteraksi dengan komponen dari paket android.widget dan android.view toolkit UI Android. Karena alasan ini, thread utama terkadang disebut UI thread. Namun, dalam keadaan khusus, thread utama aplikasi mungkin bukan UI thread-nya. Untuk informasi selengkapnya, lihat anotasi Thread.

Sistem tidak membuat thread terpisah untuk setiap instance komponen. Semua komponen yang berjalan dalam proses yang sama akan dibuat instance-nya di UI thread, dan sistem akan memanggil setiap komponen yang dikirim dari thread tersebut. Oleh karena itu, metode yang merespons callback sistem—seperti onKeyDown() untuk melaporkan tindakan pengguna, atau metode callback siklus proses—selalu berjalan di UI thread proses.

Misalnya, saat pengguna menyentuh tombol di layar, UI thread aplikasi Anda akan mengirim peristiwa sentuh ke widget, yang kemudian menetapkan status ditekan dan memposting permintaan yang tidak valid ke antrean peristiwa. UI thread akan menghapus antrean permintaan dan memberi tahu widget untuk menggambar ulang dirinya sendiri.

Kecuali jika Anda mengimplementasikan aplikasi dengan benar, model thread tunggal ini dapat menghasilkan performa yang buruk saat aplikasi melakukan pekerjaan intensif sebagai respons terhadap interaksi pengguna. Menjalankan operasi panjang di UI thread, seperti akses jaringan atau kueri database, akan memblokir seluruh UI. Jika thread diblokir, tidak ada peristiwa yang dapat dikirim, termasuk peristiwa menggambar.

Dari perspektif pengguna, aplikasi sepertinya hang. Lebih buruk lagi, jika UI thread diblokir selama lebih dari beberapa detik, pengguna akan melihat dialog "aplikasi tidak merespons" (ANR). Kemudian pengguna mungkin memutuskan untuk keluar dari aplikasi Anda atau bahkan meng-uninstalnya.

Perlu diingat bahwa toolkit UI Android tidak aman untuk thread. Jadi, jangan memanipulasi UI dari thread pekerja. Lakukan semua manipulasi pada antarmuka pengguna Anda dari UI thread. Ada dua aturan untuk model thread tunggal Android:

  1. Jangan memblokir UI thread.
  2. Jangan mengakses toolkit UI Android dari luar UI thread.

Thread pekerja

Karena model thread tunggal ini, Anda tidak memblokir UI thread untuk meningkatkan daya respons UI aplikasi. Jika Anda memiliki operasi untuk dijalankan yang tidak seketika, pastikan untuk melakukannya di thread latar belakang atau pekerja yang terpisah. Perlu diingat bahwa Anda tidak dapat mengupdate UI dari thread apa pun selain UI, atau thread utama.

Untuk membantu Anda mengikuti aturan ini, Android menawarkan beberapa cara untuk mengakses UI thread dari thread lain. Berikut ini daftar metode yang bisa membantu:

Contoh berikut menggunakan View.post(Runnable):

Kotlin

fun onClick(v: View) {
    Thread(Runnable {
        // A potentially time consuming task.
        val bitmap = processBitMap("image.png")
        imageView.post {
            imageView.setImageBitmap(bitmap)
        }
    }).start()
}

Java

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            // A potentially time consuming task.
            final Bitmap bitmap =
                    processBitMap("image.png");
            imageView.post(new Runnable() {
                public void run() {
                    imageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

Implementasi ini aman untuk thread karena operasi latar belakang dilakukan dari thread terpisah, sedangkan ImageView selalu dimanipulasi dari UI thread.

Namun, seiring dengan semakin kompleksnya operasi, kode semacam ini bisa menjadi rumit dan sulit dikelola. Untuk menangani interaksi yang lebih kompleks dengan thread pekerja, Anda dapat mempertimbangkan penggunaan Handler di thread pekerja untuk memproses pesan yang dikirim dari UI thread. Untuk penjelasan lengkap tentang cara menjadwalkan pekerjaan pada thread latar belakang dan berkomunikasi kembali ke UI thread, lihat Ringkasan Pekerjaan Latar Belakang.

Metode thread-safe

Dalam beberapa situasi, metode yang Anda implementasikan dipanggil dari lebih dari satu thread, dan oleh karena itu harus ditulis agar aman untuk thread.

Hal ini terutama berlaku untuk metode yang dapat dipanggil dari jarak jauh, seperti metode dalam layanan terikat. Jika panggilan pada metode yang diimplementasikan dalam IBinder berasal dari proses yang sama dengan IBinder berjalan, metode tersebut akan dieksekusi di thread pemanggil. Namun, jika panggilan berasal dari proses lain, metode tersebut akan dieksekusi dalam thread yang dipilih dari kumpulan thread yang dikelola oleh sistem dalam proses yang sama seperti IBinder. Tidak dieksekusi di UI thread proses.

Misalnya, meskipun metode onBind() layanan dipanggil dari UI thread proses layanan, metode yang diimplementasikan dalam objek yang ditampilkan oleh onBind(), seperti subclass yang mengimplementasikan metode panggilan prosedur jarak jauh (RPC), dipanggil dari thread dalam kumpulan. Karena layanan dapat memiliki lebih dari satu klien, lebih dari satu thread gabungan dapat berinteraksi dengan metode IBinder yang sama secara bersamaan, sehingga metode IBinder harus diimplementasikan agar aman untuk thread.

Demikian pula, penyedia materi bisa menerima permintaan data yang berasal dari proses lain. Class ContentResolver dan ContentProvider menyembunyikan detail tentang cara pengelolaan komunikasi antarproses (IPC), tetapi metode ContentProvider yang merespons permintaan tersebut—metode query(), insert(), delete(), update(), dan getType()—dipanggil dari kumpulan thread dalam proses penyedia konten, bukan UI thread untuk proses tersebut. Karena dapat dipanggil dari thread mana pun secara bersamaan, metode ini juga harus diimplementasikan agar aman untuk thread.

Komunikasi antar-proses

Android menawarkan mekanisme IPC menggunakan RPC, dengan metode yang dipanggil oleh aktivitas atau komponen aplikasi lain, tetapi dieksekusi dari jarak jauh dalam proses lain, dengan hasil yang ditampilkan kembali ke pemanggil. Hal ini mengharuskan penguraian panggilan metode dan datanya ke tingkat yang dapat dipahami sistem operasi, mentransmisikannya dari proses lokal dan ruang alamat ke proses jarak jauh dan ruang alamat, lalu menyusun ulang dan menerapkan kembali panggilan tersebut di sana.

Nilai-nilai yang dikembalikan ditransmisikan dalam arah yang berlawanan. Android menyediakan semua kode untuk melakukan transaksi IPC ini, sehingga Anda dapat berfokus pada pendefinisian dan implementasi antarmuka pemrograman RPC.

Untuk menjalankan IPC, aplikasi Anda harus diikat ke layanan menggunakan bindService(). Untuk informasi selengkapnya, lihat Ringkasan layanan.