Saya telah memeriksa dokumentasi / panduan resmi Android Looper
, Handler
dan MessageQueue
. Tapi saya tidak bisa mendapatkannya. Saya baru mengenal android, dan menjadi sangat bingung dengan konsep ini.
sumber
Saya telah memeriksa dokumentasi / panduan resmi Android Looper
, Handler
dan MessageQueue
. Tapi saya tidak bisa mendapatkannya. Saya baru mengenal android, dan menjadi sangat bingung dengan konsep ini.
A Looper
adalah loop penanganan pesan: ia membaca dan memproses item dari a MessageQueue
. The Looper
kelas biasanya digunakan dalam hubungannya dengan HandlerThread
(subclass dari Thread
).
A Handler
adalah kelas utilitas yang memfasilitasi interaksi dengan Looper
—terutama dengan memposting pesan dan Runnable
objek ke utas MessageQueue
. Ketika a Handler
dibuat, itu terikat ke tertentu Looper
(dan utas terkait dan antrian pesan).
Dalam penggunaan umum, Anda membuat dan memulai HandlerThread
, lalu membuat Handler
objek (atau objek) yang dengannya utas lain dapat berinteraksi dengan HandlerThread
instance. The Handler
harus dibuat sementara berjalan pada HandlerThread
, meskipun sekali dibuat tidak ada pembatasan pada apa benang dapat menggunakan Handler
's metode penjadwalan ( post(Runnable)
, dll)
Utas utama (alias utas UI) dalam aplikasi Android disiapkan sebagai utas penangan sebelum instance aplikasi Anda dibuat.
Selain dokumen kelas, ada diskusi bagus tentang semua ini di sini .
PS Semua kelas yang disebutkan di atas ada di dalam paket android.os
.
MessageQueue
Android API menyatakan bahwa aMessageQueue
adalah " kelas tingkat rendah yang menyimpan daftar pesan yang akan dikirim olehLooper
. "Telah diketahui secara luas bahwa memperbarui komponen UI langsung dari utas selain utas utama di android adalah ilegal . Dokumen android ini ( Menangani Operasi yang Mahal di UI Thread ) menyarankan langkah-langkah yang harus diikuti jika kita perlu memulai thread terpisah untuk melakukan pekerjaan yang mahal dan memperbarui UI setelah selesai. Idenya adalah untuk membuat objek Handler yang terkait dengan utas utama , dan memposting Runnable padanya pada waktu yang tepat. Ini
Runnable
akan dipanggil di utas utama . Mekanisme ini diimplementasikan dengan kelas Looper dan Handler .The
Looper
kelas mempertahankan MessageQueue , yang berisi daftar pesan . Karakter penting Looper adalah bahwa ini terkait dengan utas tempatLooper
dibuatnya . Asosiasi ini disimpan selamanya dan tidak dapat dipatahkan atau diubah. Perhatikan juga bahwa utas tidak dapat dikaitkan dengan lebih dari satuLooper
. Untuk menjamin pengaitan ini,Looper
disimpan dalam penyimpanan lokal-thread, dan tidak dapat dibuat melalui konstruktornya secara langsung. Satu-satunya cara untuk membuatnya adalah dengan memanggil siapkan metode statisLooper
. persiapkan metode pertama memeriksa ThreadLocaldari utas saat ini untuk memastikan bahwa belum ada Looper yang terkait dengan utas tersebut. Setelah pemeriksaan, yang baruLooper
dibuat dan disimpan diThreadLocal
. Setelah menyiapkanLooper
, kita dapat memanggil metode loop untuk memeriksa pesan baru dan harusHandler
menanganinya.Seperti namanya,
Handler
kelas ini terutama bertanggung jawab untuk menangani (menambah, menghapus, mengirim) pesan dari utas saat iniMessageQueue
. SebuahHandler
instance juga terikat ke utas. The mengikat antara Handler dan Thread dicapai melaluiLooper
danMessageQueue
. SebuahHandler
tersebut selalu terikat sebuahLooper
, dan kemudian terikat pada benang terkait denganLooper
. Tidak sepertiLooper
, beberapa contoh Handler dapat diikat ke utas yang sama. Setiap kali kita memanggil post atau metode serupa diHandler
, pesan baru ditambahkan ke terkaitMessageQueue
. Bidang target pesan disetel keHandler
contoh saat ini . KetikaLooper
menerima pesan ini, ia memanggil dispatchMessage pada bidang target pesan, sehingga pesan tersebut dirutekan kembali ke contoh Handler untuk ditangani, tetapi pada utas yang benar. Hubungan antaraLooper
,Handler
danMessageQueue
ditampilkan di bawah ini:sumber
Mari kita mulai dengan Looper. Anda dapat memahami hubungan antara Looper, Handler, dan MessageQueue dengan lebih mudah jika Anda memahami apa itu Looper. Anda juga dapat lebih memahami apa itu Looper dalam konteks kerangka GUI. Looper dibuat untuk melakukan 2 hal.
1) Looper mengubah utas normal , yang berhenti ketika
run()
metodenya kembali, menjadi sesuatu yang berjalan terus menerus hingga aplikasi Android berjalan , yang diperlukan dalam kerangka GUI (Secara teknis, ini masih berakhir ketikarun()
metode kembali. Tapi izinkan saya menjelaskan apa yang saya maksud, di bawah).2) Looper menyediakan antrian di mana pekerjaan yang harus diselesaikan diantrekan, yang juga diperlukan dalam kerangka GUI.
Seperti yang Anda ketahui, saat aplikasi diluncurkan, sistem membuat thread eksekusi untuk aplikasi tersebut, yang disebut "main", dan aplikasi Android biasanya berjalan sepenuhnya pada satu thread secara default sebagai "thread utama". Tapi utas utama bukanlah utas rahasia, utas khusus . Itu hanya utas normal yang juga dapat Anda buat dengan
new Thread()
kode, yang berarti itu berakhir ketikarun()
metodenya kembali! Pikirkan contoh di bawah ini.Sekarang, mari terapkan prinsip sederhana ini ke aplikasi Android. Apa yang akan terjadi jika aplikasi Android dijalankan di thread normal? Sebuah utas bernama "main" atau "UI" atau apa pun yang memulai aplikasi, dan menggambar semua UI. Jadi, layar pertama ditampilkan kepada pengguna. Jadi bagaimana sekarang? Utas utama berakhir? Tidak, seharusnya tidak. Itu harus menunggu sampai pengguna melakukan sesuatu, bukan? Tetapi bagaimana kita bisa mencapai perilaku ini? Nah, kita bisa coba dengan
Object.wait()
atauThread.sleep()
. Misalnya, utas utama menyelesaikan tugas awalnya untuk menampilkan layar pertama, dan tidur. Itu bangun, yang berarti terputus, ketika pekerjaan baru yang harus dilakukan diambil. Sejauh ini bagus, tapi saat ini kita membutuhkan struktur data seperti antrian untuk menampung banyak pekerjaan. Pikirkan tentang kasus ketika pengguna menyentuh layar secara berurutan, dan tugas membutuhkan waktu lebih lama untuk menyelesaikannya. Jadi, kita perlu memiliki struktur data untuk menampung pekerjaan yang harus dilakukan dengan cara pertama masuk pertama keluar. Selain itu, Anda mungkin membayangkan, mengimplementasikan thread yang selalu-berjalan-dan-proses-pekerjaan-ketika-tiba menggunakan interupsi tidaklah mudah, dan mengarah ke kode yang kompleks dan seringkali tidak dapat dikelola. Kami lebih suka membuat mekanisme baru untuk tujuan seperti itu, dan itulah Looper . The dokumen resmi kelas Loopermengatakan, "Thread secara default tidak memiliki loop pesan yang terkait dengannya", dan Looper adalah kelas "yang digunakan untuk menjalankan loop pesan untuk thread". Sekarang Anda bisa mengerti artinya.Mari pindah ke Handler dan MessageQueue. Pertama, MessageQueue adalah antrian yang saya sebutkan di atas. Itu berada di dalam Looper, dan hanya itu. Anda dapat memeriksanya dengan kode sumber kelas Looper . Kelas Looper memiliki variabel anggota MessageQueue.
Lalu, apakah Handler itu? Jika ada antrian, maka harus ada metode yang memungkinkan kita memasukkan tugas baru ke antrian, bukan? Itulah yang dilakukan Handler. Kita bisa memasukkan tugas baru ke antrean (MessageQueue) menggunakan berbagai
post(Runnable r)
metode. Itu dia. Ini semua tentang Looper, Handler, dan MessageQueue.Kata terakhir saya adalah, jadi pada dasarnya Looper adalah class yang dibuat untuk mengatasi masalah yang terjadi pada framework GUI. Tetapi kebutuhan semacam ini juga dapat terjadi dalam situasi lain. Sebenarnya ini adalah pola yang cukup terkenal untuk aplikasi multi utas, dan Anda dapat mempelajarinya lebih lanjut di "Pemrograman Bersamaan di Java" oleh Doug Lea (Terutama, bab 4.1.4 "Utas Pekerja" akan sangat membantu). Selain itu, Anda dapat membayangkan mekanisme semacam ini tidak unik dalam kerangka kerja Android, tetapi semua kerangka kerja GUI mungkin perlu serupa dengan ini. Anda dapat menemukan mekanisme yang hampir sama dalam kerangka Java Swing.
sumber
MessageQueue
: Ini adalah kelas tingkat rendah yang menyimpan daftar pesan yang akan dikirim oleh aLooper
. Pesan tidak ditambahkan secara langsung ke aMessageQueue
, melainkan melaluiHandler
objek yang terkait denganLooper
. [ 3 ]Looper
: Ini loop di atasMessageQueue
yang berisi pesan yang akan dikirim. Tugas sebenarnya dari mengatur antrian dilakukan olehHandler
yang bertanggung jawab untuk menangani (menambah, menghapus, mengirim) pesan dalam antrian pesan. [ 2 ]Handler
: Ini memungkinkan Anda untuk mengirim dan memprosesMessage
danRunnable
objek yang terkait dengan utasMessageQueue
. Setiap contoh Handler dikaitkan dengan satu utas dan antrian pesan utas itu. [ 4 ]Ketika Anda membuat yang baru
Handler
, itu terikat ke utas / antrian pesan dari utas yang membuatnya - sejak saat itu , itu akan mengirimkan pesan dan runnable ke antrian pesan itu dan mengeksekusinya saat mereka keluar dari antrian pesan .Mohon, lihat gambar di bawah [ 2 ] untuk pemahaman yang lebih baik.
sumber
Memperluas jawabannya, oleh @K_Anas, dengan contoh, Seperti yang dinyatakan
misalnya jika Anda mencoba memperbarui UI menggunakan Thread.
aplikasi Anda akan mogok dengan pengecualian.
dengan kata lain Anda perlu menggunakan
Handler
yang tetap mengacu pada tugasMainLooper
ieMain Thread
atauUI Thread
dan lulus sebagaiRunnable
.sumber