Dalam sudut pandang menjalankan kode di utas UI, apakah ada perbedaan antara:
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
atau
MainActivity.this.myView.post(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
dan
private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
protected void onPostExecute(Bitmap result) {
Log.d("UI thread", "I am the UI thread");
}
}
Jawaban:
Tidak satu pun dari mereka yang persis sama, meskipun mereka semua akan memiliki efek bersih yang sama.
Perbedaan antara yang pertama dan yang kedua adalah bahwa jika Anda berada di utas aplikasi utama saat mengeksekusi kode, yang pertama (
runOnUiThread()
) akan menjalankanRunnable
segera. Yang kedua (post()
) selalu menempatkanRunnable
di akhir antrian acara, bahkan jika Anda sudah di utas aplikasi utama.Yang ketiga, dengan asumsi Anda membuat dan mengeksekusi instance
BackgroundTask
, akan membuang banyak waktu untuk mengambil thread dari kumpulan thread, untuk mengeksekusi no-op defaultdoInBackground()
, sebelum akhirnya melakukan apa yang berarti apost()
. Sejauh ini yang paling tidak efisien dari ketiganya. GunakanAsyncTask
jika Anda benar-benar memiliki pekerjaan untuk dilakukan di utas latar belakang, bukan hanya untuk penggunaanonPostExecute()
.sumber
AsyncTask.execute()
Anda tetap harus menelepon dari utas UI, yang menjadikan opsi ini tidak berguna untuk kasus penggunaan dengan hanya menjalankan kode pada utas UI dari utas latar kecuali jika Anda memindahkan semua pekerjaan latar belakangdoInBackground()
dan menggunakannyaAsyncTask
dengan benar.AsyncTask
dari utas UI?boolean isUiThread = (Looper.getMainLooper().getThread() == Thread.currentThread());
Looper.getMainLooper().isCurrentThread
Saya suka komentar HPP , bisa digunakan di mana saja tanpa parameter apa pun:
sumber
Ada cara keempat menggunakan
Handler
sumber
new Handler(Looper.getMainLooper()).post(r)
, yang merupakan cara yang disukai sebagaiLooper.getMainLooper()
membuat panggilan statis ke utama, sedangkanpostOnUiThread()
harus memiliki instanceMainActivity
dalam lingkup.Jawaban oleh Pomber dapat diterima, namun saya bukan penggemar berat membuat objek baru berulang kali. Solusi terbaik adalah selalu yang mencoba untuk mengurangi memori babi. Ya, ada pengumpulan sampah otomatis tetapi konservasi memori dalam perangkat seluler berada dalam batas praktik terbaik. Kode di bawah ini memperbarui TextView di layanan.
Itu dapat digunakan dari mana saja seperti ini:
sumber
The best solutions are always the ones that try to mitigate memory hog
. Ada banyak kriteria lain untukbest
, dan ini memiliki sedikit baupremature optimization
. Yaitu, kecuali Anda tahu Anda menyebutnya cukup sehingga jumlah objek yang dibuat adalah masalah (dibandingkan dengan sepuluh ribu cara lain di mana aplikasi Anda mungkin membuat sampah.), Yang mungkinbest
adalah menulis yang paling sederhana (termudah untuk dipahami ) kode, dan beralih ke beberapa tugas lain.textViewUpdaterHandler
akan lebih baik diberi nama sepertiuiHandler
ataumainHandler
, karena umumnya berguna untuk setiap posting ke utas UI utama; sama sekali tidak terkait dengan kelas TextViewUpdater Anda. Saya akan memindahkannya dari sisa kode itu, dan membuatnya jelas bahwa itu dapat digunakan di tempat lain ... Sisa kode itu meragukan, karena untuk menghindari membuat satu objek secara dinamis, Anda memecahkan apa yang bisa menjadi satu panggilan ke dua langkahsetText
danpost
, itu bergantung pada objek berumur panjang yang Anda gunakan sebagai sementara. Kompleksitas yang tidak perlu, dan tidak aman untuk thread. Tidak mudah dirawat.uiHandler
dantextViewUpdater
, kemudian meningkatkan kelas Anda dengan mengubah kepublic void setText(String txt, Handler uiHandler)
dan menambahkan metode garisuiHandler.post(this);
Kemudian penelepon dapat melakukan dalam satu langkah:textViewUpdater.setText("Hello", uiHandler);
. Kemudian di masa depan, jika perlu thread aman, metode dapat membungkus pernyataannya di dalam kunci aktifuiHandler
, dan pemanggil tetap tidak berubah.Pada Android P Anda dapat menggunakan
getMainExecutor()
:Dari dokumen pengembang Android :
Dari CommonsBlog :
sumber
Jika Anda perlu menggunakan dalam Fragmen yang harus Anda gunakan
dari pada
Karena akan ada pengecualian pointer nol dalam beberapa situasi seperti pager fragmen
sumber
hi guys yang satu ini adalah pertanyaan dasar yang saya katakan
gunakan Handler
sumber
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
jika tidak dipanggil dari utas UI.