Handler vs AsyncTask vs Thread [ditutup]

382

Saya agak bingung tentang perbedaan antara Handlers, AsyncTaskdan Threadsdi Android. Saya telah membaca beberapa blog dan pertanyaan di sini di StackOverflow.

Handleradalah utas latar belakang yang memungkinkan Anda berkomunikasi dengan UI. Memperbarui bar kemajuan, misalnya, harus dilakukan melalui Handler. Menggunakan Handler Anda memiliki keunggulan MessagingQueues, jadi jika Anda ingin menjadwalkan pesan atau memperbarui beberapa elemen UI atau memiliki tugas yang berulang.

AsyncTaskserupa, pada kenyataannya, mereka menggunakan Handler, tetapi tidak berjalan di utas UI, jadi itu baik untuk mengambil data, misalnya mengambil layanan web. Nanti Anda bisa berinteraksi dengan UI.

ThreadNamun tidak dapat berinteraksi dengan UI, memberikan threading "dasar" dan Anda kehilangan semua abstraksi AsyncTask.

Namun, saya ingin koneksi soket berjalan dalam layanan. Haruskah ini dijalankan di handler atau thread, atau bahkan sebuah AsyncTask? Interaksi UI tidak diperlukan sama sekali. Apakah itu membuat perbedaan dalam hal kinerja yang saya gunakan?

Sementara itu, dokumentasi telah banyak ditingkatkan.

Alx
sumber
9
"Penangan adalah utas latar belakang" - Beberapa jawaban terpilih tampaknya juga menuju ke arah itu. Tapi itu kesalahpahaman. A Handlerbukan utas, dan tidak menjalankan apa pun. Ini hanya sarana untuk menyampaikan pesan dengan aman dari satu utas ke antrian pesan utas lainnya . Jadi, biasanya, (setidaknya) dua utas masih harus dibuat yang kemudian dapat menggunakan pawang, tetapi pawang tidak dapat menjalankan apapun dengan sendirinya.
JimmyB

Jawaban:

57

Seperti yang dijelaskan dalam Tutorial tentang pemrosesan latar belakang Android dengan Handler, AsyncTask dan Loader di situs Vogella:

The Handlerkelas dapat digunakan untuk mendaftar ke thread dan menyediakan saluran sederhana untuk mengirim data ke thread ini.

The AsyncTaskkelas merangkum penciptaan proses latar belakang dan sinkronisasi dengan thread utama. Ini juga mendukung pelaporan perkembangan tugas yang sedang berjalan.

Dan Threadpada dasarnya adalah elemen inti dari multithreading yang dapat digunakan pengembang dengan kerugian berikut:

Jika Anda menggunakan utas Java, Anda harus menangani persyaratan berikut dalam kode Anda sendiri:

  • Sinkronisasi dengan utas utama jika Anda mengirim kembali hasil ke antarmuka pengguna
  • Tidak ada standar untuk membatalkan utas
  • Tidak ada penyatuan utas standar
  • Tidak ada standar untuk menangani perubahan konfigurasi di Android

Dan mengenai AsyncTask, seperti yang dikatakan oleh Referensi Pengembang Android :

AsyncTaskmemungkinkan penggunaan utas UI yang benar dan mudah. Kelas ini memungkinkan untuk melakukan operasi latar belakang dan menerbitkan hasil pada utas UI tanpa harus memanipulasi utas dan / atau penangan.

AsyncTaskdirancang untuk menjadi kelas pembantu di sekitar Threaddan Handler dan bukan merupakan kerangka kerja threading umum. AsyncTasks idealnya harus digunakan untuk operasi pendek (paling banyak beberapa detik.) Jika Anda perlu menjaga agar thread tetap berjalan untuk jangka waktu yang lama, sangat disarankan Anda menggunakan berbagai API yang disediakan oleh paket java.util.concurrent seperti Pelaksana, ThreadPoolExecutor dan FutureTask.

Pembaruan Mei 2015: Saya menemukan serangkaian kuliah luar biasa yang membahas topik ini.

Ini adalah Pencarian Google: Douglas Schmidt memberi kuliah tentang konkurensi dan sinkronisasi android

Ini adalah video ceramah pertama di YouTube

Semua ini adalah bagian dari CS 282 (2013): Pemrograman Sistem untuk Android dari Vanderbilt University . Inilah Daftar Putar YouTube

Douglas Schmidt tampaknya menjadi dosen yang hebat

Penting: Jika Anda berada pada titik di mana Anda mempertimbangkan untuk menggunakan AsyncTaskuntuk menyelesaikan masalah threading Anda, Anda harus terlebih dahulu memeriksaReactiveX/RxAndroid pola pemrograman yang mungkin lebih tepat. Sumber yang sangat baik untuk mendapatkan ikhtisar adalah Belajar RxJava 2 untuk Android dengan contoh .

Daniel F
sumber
4
Dalam seri kuliah itu, tautan ini akan membawa Anda langsung ke beberapa contoh utas: youtu.be/4Vue_KuXfCk?t=19m24s
Aggressor
353

Jika kita melihat kode sumbernya, kita akan melihat AsyncTaskdan Handlersepenuhnya ditulis dalam Java. (Ada beberapa pengecualian. Tapi itu bukan poin penting)

Jadi tidak ada sihir di AsyncTaskatau Handler. Kelas-kelas ini membuat hidup kita lebih mudah sebagai pengembang.

Misalnya: Jika Program A memanggil metode A (), metode A () dapat berjalan di utas berbeda dengan Program A. Kami dapat dengan mudah memverifikasi dengan kode berikut:

Thread t = Thread.currentThread();    
int id = t.getId();

Mengapa kami harus menggunakan utas baru untuk beberapa tugas? Anda dapat google untuk itu. Banyak alasan, misalnya: pekerjaan berat, kerja jangka panjang.

Jadi, apa perbedaan antara Thread, AsyncTaskdan Handler?

AsyncTaskdan Handlerditulis dalam Java (secara internal mereka menggunakan a Thread), sehingga semua yang dapat kita lakukan dengan , Handleratau AsyncTaskkita dapat mencapai menggunakan Threadjuga.

Apa yang bisa Handlerdan AsyncTaskbenar - benar membantu?

Alasan yang paling jelas adalah komunikasi antara utas penelepon dan utas pekerja. ( Pemanggil Utas : Utas yang memanggil Utas Pekerja untuk melakukan beberapa tugas. Utas penelepon tidak harus menjadi utas UI). Tentu saja, kita dapat berkomunikasi antara dua utas dengan cara lain, tetapi ada banyak kelemahan (dan bahaya) karena keamanan benang.

Itu sebabnya kita harus menggunakan Handlerdan AsyncTask. Kelas-kelas ini melakukan sebagian besar pekerjaan untuk kita, kita hanya perlu tahu metode mana yang harus ditimpa.

Perbedaan antara Handlerdan AsyncTaskadalah: Gunakan AsyncTaskketika utas Pemanggil adalah Utas UI . Inilah yang dikatakan dokumen android:

AsyncTask memungkinkan penggunaan utas UI yang benar dan mudah. Kelas ini memungkinkan untuk melakukan operasi latar belakang dan menerbitkan hasil pada utas UI tanpa harus memanipulasi utas dan / atau penangan

Saya ingin menekankan dua poin:

1) Mudah menggunakan utas UI (jadi, gunakan ketika utas penelepon adalah Utas UI).

2) Tidak perlu memanipulasi penangan. (berarti: Anda dapat menggunakan Handler alih-alih AsyncTask, tetapi AsyncTask adalah pilihan yang lebih mudah).

Ada banyak hal dalam posting ini yang belum saya katakan, misalnya: apa itu UI Thread, atau mengapa lebih mudah. Anda harus mengetahui beberapa metode di balik setiap kelas dan menggunakannya, Anda akan sepenuhnya memahami alasannya.

@: ketika Anda membaca dokumen Android, Anda akan melihat:

Handler memungkinkan Anda untuk mengirim dan memproses objek Message dan Runnable yang terkait dengan MessageQueue utas

Deskripsi ini mungkin tampak aneh pada awalnya. Kita hanya perlu memahami bahwa setiap utas memiliki masing-masing antrian pesan (seperti daftar yang harus dilakukan), dan utas akan mengambil setiap pesan dan melakukannya sampai antrian pesan kosong (sama seperti kita menyelesaikan pekerjaan kita dan pergi tidur). Jadi, ketika Handlerberkomunikasi, itu hanya memberikan pesan kepada pemanggil utas dan itu akan menunggu untuk diproses.

Rumit? Ingatlah bahwa Handlerdapat berkomunikasi dengan utas penelepon dengan aman.

hqt
sumber
4
sebenarnya asynctask juga didasarkan pada handler dan futuretask, lihat
Sumit
AsyncTask pada dasarnya adalah kelas pembantu yang dibangun di atas Handler dan Thread. developer.android.com/reference/android/os/AsyncTask.html . Lihatlah dokumen "AsyncTask dirancang untuk menjadi kelas pembantu di Thread dan Handler". AsyncTask dirilis di API3 sementara Handler ada sejak API1.
hjchin
52

Setelah melihat secara mendalam, itu lurus ke depan.

AsyncTask:

Ini adalah cara sederhana untuk menggunakan utas tanpa mengetahui apa pun tentang model utas java . AsyncTaskmemberikan berbagai panggilan balik masing-masing ke utas pekerja dan utas utama.

Gunakan untuk operasi menunggu kecil seperti berikut:

  1. Mengambil beberapa data dari layanan web dan ditampilkan di atas tata letak.
  2. Permintaan basis data.
  3. Ketika Anda menyadari bahwa menjalankan operasi tidak akan pernah bersarang.

Handler:

Ketika kami menginstal aplikasi di android, maka ia membuat utas untuk aplikasi yang disebut UTAMA UI Utas. Semua aktivitas dijalankan di dalam utas itu. Dengan aturan model single thread Android, kita tidak dapat mengakses elemen UI (bitmap, textview, dll.) Secara langsung untuk utas lain yang ditentukan di dalam aktivitas itu.

Handler memungkinkan Anda untuk berkomunikasi kembali dengan utas UI dari utas latar belakang lainnya. Ini berguna di android karena android tidak mengizinkan utas lain berkomunikasi langsung dengan utas UI. Pawang dapat mengirim dan memproses objek Message dan Runnable yang terkait dengan ThreadQueue utas. Setiap instance Handler dikaitkan dengan utas tunggal dan antrian pesan utas itu. Ketika Handler baru dibuat, ia terikat ke antrian utas / pesan dari utas yang membuatnya.

Ini paling cocok untuk:

  1. Ini memungkinkan Anda untuk melakukan antrian pesan.
  2. Penjadwalan pesan.

Thread:

Sekarang saatnya berbicara tentang utas.

Thread adalah induk dari keduanya AsyncTaskdan Handler. Keduanya secara internal menggunakan utas, yang berarti Anda juga dapat membuat model utas sendiri seperti AsyncTaskdan Handler, tetapi itu membutuhkan pengetahuan yang baik tentang Implementasi Multi-Threading Java .

Lavekush Agrawal
sumber
1
AsyncTask api, pada kenyataannya, ditulis dengan Futures, Handler, dan Executors. Lihat kode sumber: grepcode.com/file_/repository.grepcode.com/java/ext/…
IgorGanapolsky
22

An AsyncTaskdigunakan untuk melakukan beberapa perhitungan latar belakang dan mempublikasikan hasilnya ke utas UI (dengan pembaruan kemajuan opsional). Karena Anda tidak peduli dengan UI, maka a Handleratau Threadtampaknya lebih tepat.

Anda dapat menelurkan latar belakang Threaddan lulus pesan kembali ke thread utama Anda dengan menggunakan Handler's postmetode.

Eugene S
sumber
9

Benang

Android mendukung Java Threads standar . Anda dapat menggunakan Thread standar dan alat-alat dari paket " java.util.concurrent" untuk meletakkan tindakan ke latar belakang. Satu-satunya batasan adalah Anda tidak dapat secara langsung memperbarui UI dari proses latar belakang.

Jika Anda perlu memperbarui UI dari tugas latar belakang, Anda perlu menggunakan beberapa kelas khusus Android. Anda dapat menggunakan kelas " android.os.Handler" untuk ini atau kelas " AsyncTask"

Handler

Kelas " Handler" dapat memperbarui UI. Pegangan menyediakan metode untuk menerima pesan dan untuk runnables. Untuk menggunakan penangan, Anda harus mensubclassnya dan mengganti handleMessage()untuk memproses pesan. Untuk memproses Runable, Anda dapat menggunakan metode ini. post();Anda hanya perlu satu instance handler dalam aktivitas Anda.

Anda dapat memposting pesan melalui metode sendMessage(Message msg)atau sendEmptyMessage.

AsyncTask

Jika Anda memiliki Activityyang perlu mengunduh konten atau melakukan operasi yang dapat dilakukan di latar belakang AsyncTaskmemungkinkan Anda untuk mempertahankan antarmuka pengguna yang responsif dan mempublikasikan perkembangan operasi tersebut kepada pengguna.

Untuk informasi lebih lanjut, Anda dapat melihat tautan ini.

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask

Harshal Benake
sumber
6

Thread:

Anda dapat menggunakan yang baru Threaduntuk tugas latar belakang yang sudah berjalan lama tanpa memengaruhi Utas UI. Dari java Thread, Anda tidak dapat memperbarui UI Thread.

Karena Thread normal tidak banyak berguna untuk arsitektur Android, kelas helper untuk threading telah diperkenalkan.

Anda dapat menemukan jawaban atas pertanyaan Anda di halaman dokumentasi kinerja Threading .

Handler :

A Handlermemungkinkan Anda untuk mengirim dan memproses pesan dan Runnableobjek yang terkait dengan utas MessageQueue. Setiap Handlerinstance dikaitkan dengan utas tunggal dan antrian pesan utas itu.

Ada dua kegunaan utama untuk Handler:

  1. Untuk menjadwalkan pesan dan runnables yang akan dieksekusi sebagai titik di masa depan;

  2. Untuk meminta tindakan dilakukan pada utas yang berbeda dari yang Anda miliki.

AsyncTask :

AsyncTaskmemungkinkan penggunaan utas UI yang benar dan mudah. Kelas ini memungkinkan Anda untuk melakukan operasi latar belakang dan menerbitkan hasil pada utas UI tanpa harus memanipulasi utas dan / atau penangan.

Kekurangan:

  1. Secara default, aplikasi mendorong semua AsyncTaskobjek yang dibuatnya menjadi satu utas. Oleh karena itu, mereka mengeksekusi secara serial, dan — seperti halnya utas utama — paket kerja yang sangat panjang dapat memblokir antrian. Karena alasan ini, gunakan AsyncTask untuk menangani item kerja yang durasinya lebih pendek dari 5 ms .

  2. AsyncTaskobjek juga merupakan pelanggar paling umum untuk masalah referensi-implisit. AsyncTaskobjek menghadirkan risiko yang terkait dengan referensi eksplisit, juga.

HandlerThread :

Anda mungkin memerlukan pendekatan yang lebih tradisional untuk mengeksekusi blok kerja pada utas yang telah berjalan lama ( tidak seperti AsyncTask, yang harus digunakan untuk beban kerja 5 ms ), dan beberapa kemampuan untuk mengelola alur kerja itu secara manual. Handler thread secara efektif adalah thread yang berjalan lama yang mengambil pekerjaan dari antrian dan beroperasi di atasnya.

ThreadPoolExecutor :

Kelas ini mengelola pembuatan sekelompok utas, menetapkan prioritas mereka, dan mengelola bagaimana pekerjaan didistribusikan di antara utas tersebut. Saat beban kerja bertambah atau berkurang, kelas berputar atau menghancurkan lebih banyak utas untuk menyesuaikan dengan beban kerja.

Jika beban kerja lebih banyak dan lajang HandlerThreadtidak cukup, Anda dapat melakukannyaThreadPoolExecutor

Namun saya ingin menjalankan koneksi soket dalam layanan. Haruskah ini dijalankan di handler atau thread, atau bahkan AsyncTask? Interaksi UI tidak diperlukan sama sekali. Apakah itu membuat perbedaan dalam hal kinerja yang saya gunakan?

Karena interaksi UI tidak diperlukan, Anda mungkin tidak menggunakan AsyncTask. Utas normal tidak banyak berguna dan karenanya HandlerThreadmerupakan pilihan terbaik. Karena Anda harus menjaga koneksi soket, Handler pada utas utama tidak berguna sama sekali. Buat HandlerThreaddan dapatkan Handlerdari looper HandlerThread.

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

Jika Anda ingin berkomunikasi kembali ke utas UI, Anda dapat menggunakan satu Handler lagi untuk memproses respons.

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

di Anda Runnable, Anda dapat menambahkan

responseHandler.sendMessage(msg);

Rincian lebih lanjut tentang implementasi dapat ditemukan di sini:

Android: Bersulang di utas

Ravindra babu
sumber
5

Menurut pendapat saya utas bukan cara yang paling efisien untuk melakukan koneksi soket tetapi mereka memberikan fungsionalitas paling dalam hal menjalankan utas. Saya mengatakan itu karena dari pengalaman, menjalankan utas untuk waktu yang lama menyebabkan perangkat menjadi sangat panas dan sumber daya intensif. Bahkan sederhana while(true)akan memanaskan telepon dalam hitungan menit. Jika Anda mengatakan bahwa interaksi UI tidak penting, mungkin yang AsyncTaskbaik karena mereka dirancang untuk proses jangka panjang. Ini hanya pendapat saya tentang itu.

MEMPERBARUI

Harap abaikan jawaban saya di atas! Saya menjawab pertanyaan ini pada tahun 2011 ketika saya tidak terlalu berpengalaman dalam Android daripada saya sekarang. Jawaban saya di atas menyesatkan dan dianggap salah. Saya meninggalkannya di sana karena banyak orang berkomentar di bawah ini untuk mengoreksi saya, dan saya telah belajar pelajaran saya.

Ada jauh lebih baik jawaban lain di utas ini, tetapi saya setidaknya akan memberi saya jawaban yang lebih tepat. Tidak ada yang salah dengan menggunakan Java biasa Thread; Namun, Anda harus benar-benar berhati-hati tentang bagaimana Anda menerapkannya karena melakukannya dengan salah dapat menjadi sangat intensif prosesor (gejala yang paling penting dapat memanaskan perangkat Anda). AsyncTasks sangat ideal untuk sebagian besar tugas yang ingin Anda jalankan di latar belakang (contoh umum adalah disk I / O, panggilan jaringan, dan panggilan basis data). Namun, AsyncTasks tidak boleh digunakan untuk proses yang sangat panjang yang mungkin perlu dilanjutkan setelah pengguna menutup aplikasi Anda atau meletakkan perangkat mereka ke standby. Saya akan mengatakan untuk sebagian besar kasus, apa pun yang tidak termasuk dalam utas UI, dapat diurus dalam AsyncTask.

Brian
sumber
terima kasih, apakah sebenarnya ada alasan saya harus menggunakan Threads bukannya AsyncTasks? Atau lebih disarankan untuk memanfaatkannya?
Alx
9
@ AeroDroid Dalam contoh Anda: "a simple while (true)", Anda akan mematok CPU di sini kecuali jika Anda menambahkan status sleep dalam loop. Ini berlaku untuk setiap loop tanpa akhir. Jika Anda ingin mengurangi penggunaan CPU karena overhead ini, tidur utas selama beberapa milidetik di akhir loop.
Kesalahan 454
1
@Error 454 - itu menarik! Jika Anda harus memilih nomor yang sesuai untuk waktu tidur, apakah itu antara 40-80 milidetik?
Abhijit
6
@Abhijit Dari hal-hal permainan yang telah saya lakukan di SDL, cukup menambahkan 10 ms sleep ke loop sudah cukup untuk turun dari 99% cpu ke ~ 0 selama status siaga.
Kesalahan 454
15
Sebenarnya developer.android.com/reference/android/os/AsyncTask.html mengatakan: "AsyncTasks idealnya harus digunakan untuk operasi PENDEK". Anda juga harus menggunakannya dengan hati-hati karena mereka dapat diberhentikan oleh sistem tanpa mengeksekusi!
type-a1pha
5

AsyncTaskdirancang untuk melakukan operasi tidak lebih dari beberapa detik untuk dilakukan di latar belakang (tidak disarankan untuk megabyte pengunduhan file dari server atau menghitung tugas intensif cpu seperti operasi IO file). Jika Anda perlu menjalankan operasi yang berjalan lama, Anda sangat disarankan untuk menggunakan utas asli java. Java memberi Anda berbagai kelas terkait utas untuk melakukan apa yang Anda butuhkan. Gunakan Handleruntuk memperbarui Thread UI.

langit
sumber
2
public class RequestHandler {

    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {

        URL url;

        StringBuilder sb = new StringBuilder();
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

}
krishna kulat
sumber
1

Biarkan saya mencoba dan menjawab pertanyaan di sini dengan contoh :) - MyImageSearch [Mohon lihat gambar di sini di layar kegiatan utama - yang berisi teks edit / tombol pencarian / tampilan kisi]

MyImageSearch

Deskripsi MyImageSearch - Setelah pengguna memasukkan detail pada bidang teks edit dan mengklik tombol pencarian, kami akan mencari gambar di internet melalui layanan web yang disediakan oleh flickr (Anda hanya perlu mendaftar di sana untuk mendapatkan kunci / token rahasia) - untuk pencarian, kami mengirim Permintaan HTTP dan MENDAPATKAN Data JSON kembali sebagai tanggapan yang berisi url gambar individual yang kemudian akan kami gunakan untuk memuat tampilan kisi.

Implementasi Saya - Dalam aktivitas utama saya akan mendefinisikan kelas dalam yang memperluas AsyncTask untuk mengirim Permintaan HTTP di doInBackGround Method dan mengambil Respons JSON dan memperbarui ArrayList lokal saya dari FlickrItems yang akan saya gunakan untuk memperbarui GridView saya melalui FlickrAdapter (perluas BaseAdapter) dan panggil adaptor.notifyDataSetChanged () di onPostExecute () dari AsyncTask untuk memuat ulang tampilan kisi. Perhatikan bahwa di sini Permintaan HTTP adalah panggilan pemblokiran karena saya telah melakukannya melalui AsyncTask. Dan, saya bisa menyimpan item dalam adaptor untuk meningkatkan kinerja atau menyimpannya di SDCard. Kisi yang akan saya gembungkan di FlickrAdapter berisi dalam implementasi saya tampilan progressbar dan gambar. Di bawah ini Anda dapat menemukan kode untuk mainActivity yang saya gunakan.

Menjawab Pertanyaan Sekarang - Jadi, begitu kita memiliki data JSON untuk mengambil masing-masing Gambar, kita dapat menerapkan logika mendapatkan gambar di latar belakang melalui Handler atau Thread atau AsyncTask. Kita harus mencatat di sini bahwa karena gambar saya setelah diunduh harus ditampilkan pada UI / utas utama, kita tidak dapat hanya menggunakan utas karena karena mereka tidak memiliki akses ke konteks. Dalam FlickrAdapter, pilihan yang dapat saya pikirkan:

  • Pilihan 1: Buat LooperThread [extends thread] - dan terus unduh gambar secara berurutan dalam satu utas dengan menjaga utas ini tetap terbuka [looper.loop ()]
  • Pilihan 2: Memanfaatkan Thread Pool dan memposting runnable melalui myHandler yang berisi referensi ke ImageView saya, tetapi karena tampilan di Grid View didaur ulang, sekali lagi masalah mungkin muncul ketika gambar pada indeks 4 ditampilkan pada indeks 9 [unduhan dapat butuh lebih banyak waktu]
  • Pilihan 3 [Saya menggunakan ini]: Manfaatkan Thread Pool dan kirim pesan ke myHandler, yang berisi data yang terkait dengan indeks ImageView dan ImageView itu sendiri, jadi saat melakukan handleMessage () kami akan memperbarui ImageView hanya jika currentIndex cocok dengan indeks dari Gambar yang kami coba unduh.
  • Pilihan 4: Manfaatkan AsyncTask untuk mengunduh gambar di latar belakang, tetapi di sini saya tidak akan memiliki akses ke jumlah utas yang saya inginkan di kumpulan utas dan ini bervariasi dengan versi android yang berbeda, tetapi dalam Pilihan 3 saya dapat membuat keputusan sadar ukuran kumpulan ulir tergantung pada konfigurasi perangkat yang digunakan.

Di sini kode sumber:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Saya harap jawaban saya lama akan membantu dalam memahami beberapa detail yang lebih baik.

akshaymani
sumber
Bolehkah saya tahu alasan mengapa penjelasan saya atas dasar contoh untuk analogi telah dipilih, sehingga saya juga belajar darinya?
akshaymani
2
pertama-tama terima kasih atas balasan Anda, meskipun topik ini agak lama konsep inti masih tetap up to date. Pertanyaan awal saya tidak dijawab sama sekali, Anda memberikan contoh dan menjelaskan cara kerjanya, tetapi pertanyaannya menanyakan perbedaan antara handler, asynctask dan utas.
Alx
@ 80 meninggalkan ok saya mengerti sekarang, saya mencoba menjelaskan bagaimana saya sampai pada kesimpulan memilih satu cara dari yang lain. Bagaimanapun, akan senang mendengar pandangan Anda / orang lain tentang apakah apa yang saya tulis itu benar atau jika dapat ditingkatkan lebih lanjut.
akshaymani
1

Itu tergantung mana yang akan dipilih berdasarkan persyaratan

Handler sebagian besar digunakan untuk beralih dari utas lain ke utas utama, Handler dilampirkan ke looper tempat ia memposting tugas yang bisa dijalankan dalam antrian. Jadi Jika Anda sudah berada di utas lainnya dan beralih ke utas utama maka Anda perlu menangani alih-alih tugas async atau utas lainnya

Jika Handler dibuat selain dari utas utama yang bukan looper tidak akan memberikan kesalahan karena gagang dibuat utas, utas itu perlu dibuat lopper

AsyncTask digunakan untuk mengeksekusi kode selama beberapa detik yang berjalan pada utas latar dan memberikan hasilnya pada utas utama ** * Batasan AsyncTask 1. Tugas Async tidak melekat pada siklus aktivitas dan tetap berjalan meskipun aktivitasnya dihancurkan sedangkan loader tidak memiliki batasan ini 2. Semua Tugas Async berbagi utas latar belakang yang sama untuk eksekusi yang juga berdampak pada kinerja aplikasi

Utas digunakan di aplikasi untuk pekerjaan latar belakang juga tetapi tidak ada panggilan balik pada utas utama. Jika persyaratan cocok dengan beberapa utas alih-alih satu utas dan yang perlu memberikan tugas berkali-kali maka pelaksana rangkaian ulir adalah opsi yang lebih baik. Persyaratan Kebutuhan Pemuatan gambar dari beberapa url seperti glide.

mani
sumber
0

Benang

Saat Anda memulai aplikasi, proses dibuat untuk mengeksekusi kode. Untuk menggunakan sumber daya komputasi secara efisien, utas dapat dimulai dalam proses sehingga beberapa tugas dapat dijalankan pada saat itu. Jadi utas memungkinkan Anda untuk membangun aplikasi yang efisien dengan memanfaatkan CPU secara efisien tanpa waktu idle.

Di Android, semua komponen dijalankan pada satu utas utama yang disebut. Sistem Android mengantri tugas dan menjalankannya satu per satu di utas utama. Saat tugas yang berjalan lama dijalankan, aplikasi menjadi tidak responsif.

Untuk mencegah hal ini, Anda dapat membuat utas pekerja dan menjalankan tugas latar belakang atau berjalan lama.

Handler

Karena Android menggunakan model single thread, komponen UI dibuat non-thread safe artinya hanya utas yang dibuat yang mengaksesnya yang berarti komponen UI harus diperbarui hanya di utas utama. Saat komponen UI berjalan di utas utama, tugas yang dijalankan pada utas pekerja tidak dapat mengubah komponen UI. Di sinilah Handler muncul. Handler dengan bantuan Looper dapat terhubung ke utas baru atau utas yang ada dan menjalankan kode yang dikandungnya pada utas yang terhubung.

Handler memungkinkan komunikasi antar utas. Dengan menggunakan Handler, utas latar belakang dapat mengirim hasil ke sana dan penangan yang terhubung ke utas utama dapat memperbarui komponen UI pada utas utama.

AsyncTask

AsyncTask yang disediakan oleh android menggunakan utas dan penangan untuk membuat menjalankan tugas-tugas sederhana di latar belakang dan memperbarui hasil dari utas latar ke utas utama mudah.

Silakan lihat thread android, handler, asynctask, dan kolam utas untuk contoh.

Arnav Rao
sumber
-1

Handler- adalah media komunikasi antara utas. Di android, sebagian besar digunakan untuk berkomunikasi dengan utas utama dengan membuat dan mengirim pesan melalui handler

AsyncTask- Digunakan untuk melakukan aplikasi yang berjalan lama di utas latar belakang. Dengan n, AsyncTaskAnda dapat melakukan operasi di utas latar belakang dan mendapatkan hasil di utas utama aplikasi.

Thread- adalah proses yang ringan, untuk mencapai konkurensi dan pemanfaatan cpu maksimum. Di android Anda dapat menggunakan utas untuk melakukan aktivitas yang tidak menyentuh UI aplikasi

arjun
sumber