Mengutip dokumentasi untuk AsyncTask yang ditemukan di sini , dikatakan:
AsyncTasks idealnya digunakan untuk operasi singkat (paling lama beberapa detik.) Jika Anda perlu menjaga agar utas tetap berjalan untuk jangka waktu yang lama, sangat disarankan Anda menggunakan berbagai API yang disediakan oleh pacakge java.util.concurrent seperti Pelaksana, ThreadPoolExecutor, dan FutureTask.
Sekarang pertanyaan saya muncul: mengapa? The doInBackground()
fungsi berjalan off thread UI jadi apa salahnya dengan memiliki operasi lama berjalan di sini?
android
android-asynctask
pengguna1730789
sumber
sumber
doInBackground
fungsi yang berjalan lama membekukan layar jika bilah kemajuan tidak digunakan.Jawaban:
Ini adalah pertanyaan yang sangat bagus, dibutuhkan waktu sebagai Pemrogram Android untuk sepenuhnya memahami masalahnya. Memang AsyncTask memiliki dua masalah utama yang berkaitan:
Di dalam aplikasi RoboSpice Motivations ( tersedia di Google Play ) kami menjawab pertanyaan itu secara rinci. Ini akan memberikan pandangan mendalam tentang AsyncTasks, Loader, fitur dan kekurangannya dan juga memperkenalkan Anda pada solusi alternatif untuk permintaan jaringan: RoboSpice. Permintaan jaringan adalah persyaratan umum di Android dan pada dasarnya operasi yang berjalan lama. Berikut adalah kutipan dari aplikasi:
AsyncTask dan siklus hidup Aktivitas
AsyncTasks tidak mengikuti siklus hidup instance Aktivitas. Jika Anda memulai AsyncTask di dalam sebuah Aktivitas dan Anda memutar perangkat, Aktivitas tersebut akan dimusnahkan dan sebuah instance baru akan dibuat. Tapi AsyncTask tidak akan mati. Itu akan terus hidup sampai selesai.
Dan setelah selesai, AsyncTask tidak akan memperbarui UI Aktivitas baru. Memang itu memperbarui contoh sebelumnya dari aktivitas yang tidak ditampilkan lagi. Hal ini dapat menyebabkan Pengecualian tipe java.lang.IllegalArgumentException: Tampilan tidak dilampirkan ke pengelola jendela jika Anda menggunakan, misalnya, findViewById untuk mengambil tampilan di dalam Aktivitas.
Masalah kebocoran memori
Sangat mudah untuk membuat AsyncTasks sebagai kelas dalam Aktivitas Anda. Karena AsyncTask perlu memanipulasi tampilan Aktivitas saat tugas selesai atau sedang berlangsung, penggunaan kelas dalam dari Aktivitas tampaknya nyaman: kelas dalam dapat mengakses langsung bidang apa pun dari kelas luar.
Namun demikian, itu berarti kelas dalam akan menyimpan referensi tak terlihat pada contoh kelas luarnya: Aktivitas.
Dalam jangka panjang, ini menghasilkan kebocoran memori: jika AsyncTask bertahan lama, itu membuat aktivitas "hidup" sedangkan Android ingin membuangnya karena tidak bisa lagi ditampilkan. Aktivitas tidak dapat dikumpulkan sampah dan itu adalah mekanisme utama Android untuk menjaga sumber daya di perangkat.
Ini benar-benar ide yang sangat buruk untuk menggunakan AsyncTasks untuk operasi yang berjalan lama. Namun demikian, mereka baik-baik saja untuk yang berumur pendek seperti memperbarui Tampilan setelah 1 atau 2 detik.
Saya mendorong Anda untuk mengunduh aplikasi RoboSpice Motivations , itu benar-benar menjelaskan hal ini secara mendalam dan memberikan contoh dan demonstrasi tentang berbagai cara untuk melakukan beberapa operasi latar belakang.
sumber
Karena
AsyncTask
, secara default, menggunakan kumpulan thread yang tidak Anda buat . Jangan pernah mengikat sumber daya dari pangkalan yang tidak Anda buat, karena Anda tidak tahu apa persyaratan pangkalan itu. Dan jangan pernah mengikat sumber daya dari kumpulan yang tidak Anda buat jika dokumentasi untuk kumpulan tersebut memberi tahu Anda untuk tidak melakukannya, seperti yang terjadi di sini.Secara khusus, dimulai dengan Android 3.2, kumpulan utas yang digunakan secara
AsyncTask
default (untuk aplikasi denganandroid:targetSdkVersion
set ke 13 atau lebih tinggi) hanya memiliki satu utas di dalamnya - jika Anda mengikat utas ini tanpa batas waktu, tidak ada tugas Anda yang lain yang akan berjalan.sumber
Service
, gunakan aThread
atau aThreadPoolExecutor
.TimerTask
berasal dari Java standar, bukan Android.TimerTask
sebagian besar telah ditinggalkan demiScheduledExecutorService
(yang, terlepas dari namanya, sebagai bagian dari Java standar). Tidak ada yang terikat dengan Android, jadi Anda masih memerlukan layanan jika mengharapkan hal-hal itu berjalan di latar belakang. Dan, Anda benar - benar harus mempertimbangkanAlarmManager
, dari Android, jadi Anda tidak perlu layanan berkeliaran hanya menonton jam berdetak.Tugas Aysnc adalah utas khusus yang masih dimaksudkan untuk digunakan dengan GUI aplikasi Anda, tetapi tetap mempertahankan tugas utas UI yang banyak sumber daya. Jadi, ketika hal-hal seperti memperbarui daftar, mengubah tampilan, dll. Mengharuskan Anda melakukan beberapa operasi pengambilan atau memperbarui operasi, Anda harus menggunakan tugas asinkron sehingga Anda dapat menjauhkan operasi ini dari UI thread tetapi perhatikan bahwa operasi ini masih terhubung ke UI entah bagaimana caranya. .
Untuk tugas yang berjalan lebih lama, yang tidak memerlukan pembaruan UI, Anda bisa menggunakan layanan karena mereka bisa hidup bahkan tanpa UI.
Jadi untuk tugas-tugas singkat, gunakan tugas-tugas asinkron karena mereka bisa terbunuh oleh OS setelah aktivitas pemijahan Anda mati (biasanya tidak akan mati di tengah operasi tetapi akan menyelesaikan tugasnya). Dan untuk tugas yang panjang dan berulang, gunakan layanan sebagai gantinya.
untuk info lebih lanjut, Lihat utas:
AsyncTask lebih dari beberapa detik?
dan
AsyncTask tidak akan berhenti meskipun aktivitas telah dimusnahkan
sumber
Masalah dengan AsyncTask adalah jika ia didefinisikan sebagai kelas dalam non-statis aktivitas, ia akan memiliki referensi ke aktivitas. Dalam skenario di mana aktivitas penampung tugas asinkron selesai, tetapi pekerjaan latar belakang di AsyncTask berlanjut, objek aktivitas tidak akan dikumpulkan sampah karena ada referensi ke sana, hal ini menyebabkan kebocoran memori.
Solusi untuk memperbaikinya adalah dengan mendefinisikan tugas asinkron sebagai kelas dalam statis aktivitas dan menggunakan referensi lemah ke konteks.
Namun tetap saja, sebaiknya gunakan untuk tugas latar belakang yang sederhana dan cepat. Untuk mengembangkan aplikasi dengan kode bersih, lebih baik menggunakan RxJava untuk menjalankan tugas latar belakang yang kompleks dan memperbarui UI dengan hasil darinya.
sumber