Dalam layanan android saya telah membuat utas untuk melakukan tugas latar belakang.
Saya memiliki situasi di mana utas perlu memposting tugas tertentu pada antrian pesan utas, misalnya a Runnable
.
Apakah ada cara untuk mendapatkan Handler
utas utama dan memposting Message
/ Runnable
utasnya dari utas saya yang lain?
Terima kasih,
Jawaban:
CATATAN: Jawaban ini telah mendapatkan begitu banyak perhatian, sehingga saya perlu memperbaruinya. Sejak jawaban asli diposting, komentar dari @dzeikei hampir mendapat perhatian sama seperti jawaban aslinya. Jadi, inilah 2 solusi yang mungkin:
1. Jika utas latar belakang Anda memiliki referensi ke
Context
objek:Pastikan utas pekerja latar belakang Anda memiliki akses ke objek Konteks (bisa konteks Aplikasi atau konteks Layanan). Kemudian lakukan ini di utas latar belakang pekerja:
2. Jika utas latar belakang Anda tidak memiliki (atau membutuhkan)
Context
objek(disarankan oleh @dikeikei):
sumber
Handler
(atau menggunakanHandler.Callback
antarmuka)handleMessage()
metode Anda HANYA akan dipanggil untuk pesan yang telah diposting menggunakan handler Anda. Utas utama menggunakan penangan yang berbeda untuk mengirim / memproses pesan sehingga tidak ada konflik.Handler mainHandler = new Handler(Looper.getMainLooper());
new Runnable(){@Override public void run() {....}};
Sebagai komentator di bawah ini menunjuk dengan benar, ini bukan solusi umum untuk layanan, hanya untuk utas yang diluncurkan dari aktivitas Anda (layanan dapat berupa utas tersebut, tetapi tidak semuanya). Pada topik rumit komunikasi layanan-aktivitas, harap baca seluruh bagian Layanan pada dokumen resmi - ini rumit, jadi akan sangat membantu untuk memahami dasar-dasarnya: http://developer.android.com/guide/components/services.html #Notifikasi
Metode di bawah ini dapat berfungsi dalam kasus yang paling sederhana.
Jika saya mengerti Anda dengan benar, Anda memerlukan beberapa kode yang akan dieksekusi di utas GUI dari aplikasi (tidak dapat memikirkan hal lain yang disebut utas "utama"). Untuk ini ada metode di
Activity
:Doc: http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
Semoga ini yang Anda cari.
sumber
Service
. Anda tidak dapat menggunakanrunOnUiThread()
dalamService
. Jawaban ini menyesatkan dan tidak menjawab pertanyaan yang diajukan.Ada cara sederhana lain, jika Anda tidak memiliki akses ke Konteks.
1). Buat penangan dari looper utama:
2). Menerapkan antarmuka Runnable:
3). Poskan Runnable Anda ke uiHandler:
Itu saja ;-) Bersenang-senang dengan utas, tapi jangan lupa untuk menyinkronkannya.
sumber
Jika Anda menjalankan kode dalam utas, mis. Lakukan penundaan beberapa tindakan, maka Anda perlu memohon
runOnUiThread
dari konteksnya. Misalnya, jika kode Anda berada di dalamMainActivity
kelas maka gunakan ini:Jika metode Anda dapat dipanggil baik dari utas utama (UI) atau dari utas lainnya Anda perlu pemeriksaan seperti:
sumber
Service
. Anda tidak dapat menggunakanrunOnUiThread()
dalamService
.Activity
dokumentasi,runOnUiThread()
adalah metodeActivity
. Ini bukan metodeService
, karena itu Anda tidak dapat menggunakannya. Apa yang bisa lebih jelas dari itu?Blok kode terkondensasi adalah sebagai berikut:
Ini tidak termasuk meneruskan referensi Kegiatan atau referensi Aplikasi.
Kotlin Equivalent:
sumber
Versi Kotlin
Saat Anda melakukan suatu kegiatan , maka gunakan
Ketika Anda memiliki konteks aktivitas , mContext kemudian gunakan
Ketika Anda berada di suatu tempat di mana tidak ada konteks yang tersedia , maka gunakan
sumber
runOnUiThread(){...}
Cara paling sederhana terutama jika Anda tidak memiliki konteks, jika Anda menggunakan RxAndroid yang dapat Anda lakukan:
sumber
Kode Kotlin yang lebih tepat menggunakan handler:
sumber
Salah satu metode yang dapat saya pikirkan adalah ini:
1) Biarkan UI mengikat ke layanan.
2) Paparkan metode seperti di bawah ini oleh
Binder
yang mendaftarkan AndaHandler
:3) Di utas UI, panggil metode di atas setelah mengikat ke layanan:
4) Gunakan pawang di utas Layanan untuk mengirim tugas Anda:
sumber
HandlerThread
adalah pilihan yang lebih baik untuk Thread java normal di Android.requestHandler
post
sebuahRunnable
tugas direquestHandler
Komunikasi dengan UI Thread dari
HandlerThread
Handler
denganLooper
utas utama:responseHandler
dan gantihandleMessage
metodeRunnable
tugas Thread lain (HandlerThread
dalam hal ini), panggilansendMessage
diresponseHandler
sendMessage
Doa hasil inihandleMessage
diresponseHandler
.Message
dan proses, perbarui UIContoh : Pembaruan
TextView
dengan data yang diterima dari layanan web. Karena layanan web harus dijalankan pada utas non-UI, dibuatHandlerThread
untuk Operasi Jaringan. Setelah Anda mendapatkan konten dari layanan web, kirim pesan ke penangan utas utama Anda (Utas UI) dan ituHandler
akan menangani pesan dan perbarui UI.Kode sampel:
Artikel yang berguna:
handlerthreads-and-why-you-should-be-use-them-in-your-android-apps
android-looper-handler-handlerthread-i
sumber
Saya tahu ini adalah pertanyaan lama, tetapi saya menemukan thread utama satu-liner yang saya gunakan di Kotlin dan Java. Ini mungkin bukan solusi terbaik untuk layanan, tetapi untuk memanggil sesuatu yang akan mengubah UI di dalam sebuah fragmen, ini sangat sederhana dan jelas.
Jawa (8):
Kotlin:
sumber
Ikuti metode ini. Dengan menggunakan cara ini, Anda cukup memperbarui UI dari utas latar belakang. runOnUiThread bekerja pada utas utama (UI). Saya pikir cuplikan kode ini tidak terlalu rumit dan mudah, terutama untuk pemula.
dalam hal layanan
buat handler di oncreate
lalu gunakan seperti ini
sumber
untuk Kotlin, Anda dapat menggunakan Anko corountines :
memperbarui
usang
sumber
Jadi yang paling berguna adalah melakukan semacam:
Dan kemudian:
sumber
Ini juga dapat bekerja di kelas layanan tanpa masalah.
sumber
Dengan Kotlin, persis seperti ini di dalam fungsi apa pun:
sumber
Activity
.