Handler vs AsyncTask vs Konu [kapalı]


382

Biraz arasındaki farklar hakkında karıştı Handlers, AsyncTaskve ThreadsAndroid'de. StackOverflow'da birkaç blog ve soru okudum.

Handlerkullanıcı arayüzüyle iletişim kurmanızı sağlayan arka plan iş parçacıklarıdır. Örneğin, bir ilerleme çubuğunun güncellenmesi yoluyla yapılmalıdır Handler. İşleyicileri kullanma avantajına sahip olursunuz MessagingQueues, bu nedenle iletileri planlamak veya birden çok kullanıcı arayüzü öğesini güncellemek veya tekrarlanan görevlere sahip olmak istiyorsanız.

AsyncTaskaslında benzerdir, HandlerUI iş parçacığından yararlanırlar , ancak çalışmazlar, bu nedenle veri almak için, örneğin web hizmetlerini almak için iyidir. Daha sonra kullanıcı arayüzüyle etkileşime geçebilirsiniz.

Threadancak kullanıcı arayüzü ile etkileşime giremez, daha "temel" iş parçacığı sağlar ve tüm soyutlamaları kaçırırsınız AsyncTask.

Ancak, bir soket bağlantısı hizmet çalıştırmak istiyorum. Bu bir işleyici, iş parçacığı, hatta bir iş parçacığında mı çalıştırılmalıdır AsyncTask? UI etkileşimi hiç gerekli değildir. Kullandığım performans açısından bir fark yaratıyor mu?

Bu arada, belgeler büyük ölçüde geliştirildi.



9
"İşleyiciler arka plan iş parçacıklarıdır" - En çok oy alan cevapların bazıları da bu yöne gidiyor gibi görünüyor. Ama bu bir yanlış anlama. A Handlerbir iş parçacığı değildir ve hiçbir şey yürütmez. Bu, yalnızca iletileri bir iş parçacığından başka bir iş parçacığının ileti sırasına güvenli bir şekilde iletmenin bir yoludur . Bu nedenle, normal olarak, (en azından) iki iş parçacığı hala oluşturulmalıdır, bu daha sonra bir işleyici kullanabilir , ancak işleyici hiçbir şeyi kendisi gerçekleştiremez.
JimmyB

Yanıtlar:


57

Vogella sitesindeki Handlers, AsyncTask ve Loaders ile Android arka plan işlemesi öğreticisinin belirttiği gibi:

HandlerSınıf bir konuya kaydetmek için kullanılan ve bu konuya veri göndermek için basit bir kanal sağlar edilebilir.

AsyncTaskSınıf bir arka plan işlemi oluşturulmasını ve ana iplik ile senkronizasyon kapsüller. Ayrıca çalışan görevlerin ilerleme durumunu bildirmeyi de destekler.

Ve a Threadtemel olarak bir geliştiricinin aşağıdaki dezavantajla kullanabileceği çok iş parçacığının temel öğesidir:

Java iş parçacıklarını kullanıyorsanız, kendi kodunuzda aşağıdaki gereksinimleri karşılamanız gerekir:

  • Sonuçları kullanıcı arayüzüne geri gönderirseniz ana iş parçacığıyla senkronizasyon
  • İleti dizisini iptal etmek için varsayılan değer yok
  • Varsayılan iş parçacığı havuzu yok
  • Android'de yapılandırma değişikliklerini işlemek için varsayılan değer yok

Ve ilişkin AsyncTaskolarak Android Geliştirici Başvurusu koyar o:

AsyncTaskUI iş parçacığının düzgün ve kolay kullanımını sağlar. Bu sınıf, iş parçacıklarını ve / veya işleyicileri değiştirmek zorunda kalmadan arka plan işlemleri gerçekleştirmeye ve sonuçları UI iş parçacığında yayınlamaya izin verir.

AsyncTasketrafında yardımcı bir sınıf olarak tasarlanmıştır Threadve Handler genel bir iş parçacığı çerçevesi oluşturmaz. AsyncTasks ideal olarak kısa işlemler için kullanılmalıdır (en fazla birkaç saniye). İş parçacıklarını uzun süre çalışmaya devam etmeniz gerekiyorsa, java.util.concurrent paketi tarafından sağlanan çeşitli API'ları kullanmanız önemle tavsiye edilir. Yürütücü, ThreadPoolExecutor ve FutureTask.

Mayıs 2015 Güncellemesi: Bu konuyu kapsayan bir dizi ders buldum .

Bu Google Arama: Douglas Schmidt ders android eşzamanlılık ve senkronizasyon

Bu, YouTube'daki ilk dersin videosu

Bütün bunlar bir parçası olan Android için Programlama Sistemleri: CS 282 (2013) adlı Vanderbilt Üniversitesi . İşte YouTube Oynatma Listesi

Douglas Schmidt mükemmel bir öğretim görevlisi gibi görünüyor

Önemli:AsyncTask İplik takma sorunlarınızı çözmek için kullanmayı düşündüğünüz bir noktadaysanız, öncelikle daha uygun bir programlama modeli olup olmadığını kontrol etmelisinizReactiveX/RxAndroid . Genel bir bakış için çok iyi bir kaynak , Android için RxJava 2'yi örnek olarak öğrenmektir .


4
Bu ders dizisinde, bu bağlantı sizi bazı konu örneklerine yönlendirecektir: youtu.be/4Vue_KuXfCk?t=19m24s
Saldırgan

353

Kaynak koduna bakarsak , sadece Java ile yazılır AsyncTaskve Handleryazılır. (Yine de bazı istisnalar vardır. Ancak bu önemli bir nokta değildir)

Yani AsyncTaskveya içinde sihir yoktur Handler. Bu sınıflar bir geliştirici olarak hayatımızı kolaylaştırır.

Örneğin: Program A yöntem A () yöntemini çağırırsa, yöntem A () Program A ile farklı bir iş parçacığında çalışabilir: Aşağıdaki kodu kullanarak kolayca doğrulama yapabiliriz:

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

Neden bazı görevler için yeni bir iş parçacığı kullanmalıyız? Bunun için google. Birçok sebep, örneğin: ağır kaldırma, uzun süreli çalışmalar.

Yani, arasındaki farklar nelerdir Thread, AsyncTaskve Handler?

AsyncTaskve HandlerJava ile yazılmıştır (dahili olarak a kullanırlar Thread), böylece yapabileceğimiz her şeyi Handlerveya AsyncTaskkullanarak da başarabiliriz Thread.

Ne yapabilir HandlerveAsyncTask gerçekten yardımcı olabilir?

Bunun en açık nedeni, arayan iş parçacığı ile çalışan iş parçacığı arasındaki iletişimdir. ( Arayan İş Parçacığı : Bazı görevleri gerçekleştirmek Çalışan İş Parçasını çağıran bir iş parçacığı. Arayan iş parçacığının UI iş parçacığı olması gerekmez). Elbette, iki iplik arasında başka şekillerde iletişim kurabiliriz, ancak iplik güvenliği nedeniyle birçok dezavantaj (ve tehlike) vardır.

Bu yüzden kullanmalıyız Handler veAsyncTask . Bu sınıflar işin çoğunu bizim için yapıyor, sadece hangi yöntemleri geçersiz kılacağımızı bilmemiz gerekiyor.

Arasındaki fark Handlerve AsyncTaskgeçerli: Kullanım AsyncTasksırasında Arayan iş parçacığı bir olan UI Konu . Android belgesi şöyle diyor:

AsyncTask, UI iş parçacığının düzgün ve kolay kullanımını sağlar. Bu sınıf, iş parçacıklarını ve / veya işleyicileri değiştirmek zorunda kalmadan arka plan işlemleri gerçekleştirmeye ve sonuçları UI iş parçacığında yayınlamaya izin verir

İki noktayı vurgulamak istiyorum:

1) UI dişinin kolay kullanımı (bu nedenle, arayan ipliği UI Dişi olduğunda kullanın).

2) İşleyicileri manipüle etmeye gerek yok. (anlamına gelir: AsyncTask yerine Handler kullanabilirsiniz, ancak AsyncTask daha kolay bir seçenektir).

Bu yazıda henüz söylemediğim birçok şey var, örneğin: UI İş Parçacığı nedir veya neden daha kolay. Her sınıfın arkasındaki bazı yöntemleri bilmeli ve kullanmalısınız, nedenini tamamen anlayacaksınız.

@: Android belgesini okuduğunuzda şunu görürsünüz:

İşleyici, bir iş parçacığının MessageQueue ile ilişkili Message ve Runnable nesnelerini göndermenizi ve işlemenizi sağlar

Bu açıklama ilk başta garip gelebilir. Sadece her bir iş parçacığının her mesaj kuyruğuna (yapılacaklar listesi gibi) sahip olduğunu anlamamız gerekir ve iş parçacığı her mesajı alır ve mesaj kuyruğu boşalana kadar yapar (işimizi bitirip yatağa gider gibi). Öyleyse ne zamanHandler iletişim , arayan iş parçacığına bir mesaj verir ve işlemek için bekler.

Karmaşık? Sadece Handlerarayanın iş parçacığı ile güvenli bir şekilde iletişim kurabileceğini unutmayın .


4
aslında asynctask da işleyici ve gelecek görevlerine dayanıyor, bkz.
Sumit

AsyncTask aslında Handler ve Thread üzerine kurulmuş bir yardımcı sınıftır. developer.android.com/reference/android/os/AsyncTask.html . "AsyncTask, İş Parçacığı ve İşleyici etrafında yardımcı bir sınıf olarak tasarlanmıştır" belgesine bakın. AsyncTask API3'te yayınlanırken, Handler API1'den beri mevcuttur.
hjchin

52

Derinlemesine baktıktan sonra, doğrudan ileri.

AsyncTask:

Java iplik modeli hakkında hiçbir şey bilmeden bir iplik kullanmanın basit bir yoludur . AsyncTaskçalışan iş parçacığı ve ana iş parçacığına ilişkin çeşitli geri çağrılar verir.

Aşağıdaki gibi küçük bekleme işlemleri için kullanın:

  1. Web hizmetlerinden bazı veriler getiriliyor ve düzen üzerinde görüntüleniyor.
  2. Veritabanı sorgusu.
  3. Koşma işleminin asla iç içe olmayacağını anladığınızda.

Handler:

Android'e bir uygulama yüklediğimizde, MAIN UI Thread adlı uygulama için bir iş parçacığı oluşturur. Tüm aktiviteler bu konu içinde çalışır. Android tek iş parçacığı modeli kuralıyla, bu etkinliğin içinde tanımlanan başka bir iş parçacığı için doğrudan UI öğelerine (bitmap, textview vb.) Erişemeyiz.

Bir işleyici, diğer arka plan iş parçacıklarından gelen UI iş parçacığı ile iletişim kurmanızı sağlar. Android, diğer iş parçacıklarının UI iş parçacığı ile doğrudan iletişim kurmasına izin vermediğinden, bu Android'de kullanışlıdır. Bir işleyici, bir iş parçacığının MessageQueue ile ilişkili Message ve Runnable nesneleri gönderebilir ve işleyebilir. Her Handler örneği tek bir iş parçacığı ve o iş parçacığının ileti kuyruğu ile ilişkilendirilir. Yeni bir İşleyici oluşturulduğunda, onu oluşturan iş parçacığının iş parçacığı / ileti kuyruğuna bağlanır.

Aşağıdakiler için en uygun çözüm:

  1. Mesaj kuyruğu yapmanıza izin verir.
  2. Mesaj planlama.

Thread:

Şimdi konu hakkında konuşma zamanı.

Konu her ikisinin de üst öğesidir AsyncTaskveHandler . Her ikisi de dahili olarak iş parçacığı kullanır, bu da kendi iş parçacığı modeliniziAsyncTask ve gibi oluşturabileceğiniz anlamına gelir Handler, ancak bu Java'nın Çok İş Parçacığı Uygulaması hakkında iyi bir bilgi gerektirir .


1
AsyncTask api aslında Futures, Handler ve Execrators ile yazılmıştır. Kaynak koduna bakın: grepcode.com/file_/repository.grepcode.com/java/ext/…
IgorGanapolsky

22

Bir AsyncTaskarka plan hesaplaması yapmak ve sonucu UI iş parçacığında yayınlamak için kullanılır (isteğe bağlı ilerleme güncellemeleriyle birlikte). Kullanıcı arayüzüyle ilgilenmediğiniz için, a HandlerveyaThread daha uygun görünüyor.

'S yöntemini Threadkullanarak bir arka plan oluşturabilir ve mesajları ana mesaj dizinize geri aktarabilirsiniz .Handlerpost


9

Konu

Android, standart Java Konularını destekler . java.util.concurrentEylemleri arka plana koymak için standart Konular'ı ve “ ” paketindeki araçları kullanabilirsiniz . Tek sınırlama, bir arka plan işleminden doğrudan kullanıcı arayüzünü güncelleyememenizdir.

Kullanıcı arayüzünü bir arka plan görevinden güncellemeniz gerekiyorsa, Android'e özgü bazı sınıflar kullanmanız gerekir. Bunun android.os.Handleriçin “ AsyncTask” sınıfını veya “ ” sınıfı için kullanabilirsiniz

Handler

" Handler" Sınıfı kullanıcı arayüzünü güncelleyebilir. Tanıtıcı, ileti alma ve çalıştırılabilirler için yöntemler sağlar. Bir işleyici kullanmak için, alt sınıfı sınıflandırmanız ve handleMessage()iletileri işlemek için geçersiz kılmanız gerekir . İşlem yapmak için Runable, post();etkinliğinizde yalnızca bir işleyici örneğine ihtiyacınız vardır.

İleti diziniz yöntem yoluyla sendMessage(Message msg)veya ileti gönderebilir sendEmptyMessage.

AsyncTask

Activityİçeriği indirmeniz veya arka planda yapılabilecek işlemleri yapmanız gerekiyorsaAsyncTask Bir esnek kullanıcı arayüzü korumak ve kullanıcıya bu işlemler için ilerleme yayınlamak için izin verir.

Daha fazla bilgi için bu bağlantılara göz atabilirsiniz.

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

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


6

Thread:

Sen-ebilmek kullanma yeni Thread UI Konu etkilemeden arka plan görevleri uzun çalıştırmak için. Java Thread'den UI Thread'i güncelleyemezsiniz.

Normal İpliğinden beri , Android mimarisi için çok yararlı olmadığından, iş parçacığı için yardımcı sınıflar tanıtıldı.

İş parçacığı performansında sorgularınızın yanıtlarını bulabilirsiniz belgeleri sayfasında bulabilirsiniz.

İşleyici :

A Handler, Runnablebir evre ile ilişkili Mesaj ve nesneleri göndermenizi ve işlemenizi sağlar MessageQueue. Her Handlerörnek tek bir iş parçacığı ve o iş parçacığının ileti kuyruğu ile ilişkilendirilir.

Aşağıdakiler için iki ana kullanım vardır Handler:

  1. İleride bir nokta olarak çalıştırılacak mesajları ve runnable'ları programlamak için;

  2. Kendinizden farklı bir iş parçacığında gerçekleştirilecek bir eylemi sıralamak için.

AsyncTask :

AsyncTaskUI iş parçacığının düzgün ve kolay kullanımını sağlar. Bu sınıf, iş parçacıklarını ve / veya işleyicileri değiştirmek zorunda kalmadan arka plan işlemleri gerçekleştirmenize ve sonuçları UI iş parçacığında yayınlamanıza olanak tanır.

Dezavantajları:

  1. Varsayılan olarak, bir uygulama AsyncTaskoluşturduğu tüm nesneleri tek bir iş parçacığına iter . Bu nedenle, seri şekilde yürütülürler ve - ana iş parçacığında olduğu gibi - özellikle uzun bir çalışma paketi kuyruğu engelleyebilir. Bu nedenden dolayı, daha kısa sap iş kalemleri için AsyncTask kullanmak süresi 5ms .

  2. AsyncTasknesneler ayrıca örtük referans sorunları için en yaygın suçlulardır. AsyncTasknesneler de açık referanslarla ilgili riskler arz etmektedir.

Konu :

Uzun süren bir iş parçacığında ( 5ms iş yükü için kullanılması gereken AsyncTask'ın aksine) bir iş bloğu yürütmek ve bu iş akışını manuel olarak yönetmek için daha geleneksel bir yaklaşıma ihtiyacınız olabilir . Bir işleyici iş parçacığı, etkili bir şekilde bir kuyruktan yakalanan ve üzerinde çalışan uzun bir iş parçacığıdır.

ThreadPoolExecutor :

Bu sınıf bir grup iş parçacığının oluşturulmasını yönetir, önceliklerini belirler ve işin bu iş parçacıkları arasında nasıl dağıtılacağını yönetir. İş yükü arttıkça veya azaldıkça, sınıf iş yüküne uyum sağlamak için daha fazla iş parçacığı döndürür veya yok eder.

İş yükü daha HandlerThreadfazlaysa ve bekar ise yeterli olmazsa,ThreadPoolExecutor

Ancak bir soket bağlantısı hizmet çalıştırmak istiyorum. Bu bir işleyici, iş parçacığı, hatta bir AsyncTask içinde çalıştırılmalı mıdır? UI etkileşimi hiç gerekli değildir. Kullandığım performans açısından bir fark yaratıyor mu?

Kullanıcı arabirimi etkileşimi gerekli olmadığından, gitmeyebilirsiniz AsyncTask. Normal dişler çok kullanışlı değildir ve bu nedenle HandlerThreaden iyi seçenektir. Soket bağlantısını sürdürmeniz gerektiğinden, ana iplik üzerindeki İşleyici hiç kullanışlı değildir. Bir oluşturun HandlerThreadve bir Handlerlüperden bir olsun HandlerThread.

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

Kullanıcı arabirimi iş parçacığına geri iletişim kurmak istiyorsanız, yanıtı işlemek için bir işleyici daha kullanabilirsiniz.

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();
        }
    };

içine Runnableekleyebilirsiniz

responseHandler.sendMessage(msg);

Uygulama hakkında daha fazla ayrıntıyı burada bulabilirsiniz:

Android: Bir iş parçacığında kızarmış ekmek


5

Bence iş parçacığı soket bağlantıları yapmanın en etkili yolu değil, iş parçacığı çalıştırma açısından en işlevselliği sağlar. Diyorum ki, deneyimden dolayı, uzun süre iş parçacığı çalıştırmak, cihazların çok sıcak ve kaynak yoğun olmasına neden olur. Basit while(true)bir telefon bile dakikalar içinde ısınır. Kullanıcı arayüzü etkileşiminin önemli olmadığını söylerseniz, belki de AsyncTaskiyidir, çünkü bunlar uzun vadeli süreçler için tasarlanmıştır. Bu sadece benim görüşüm.

GÜNCELLEME

Lütfen yukarıdaki cevabımı dikkate almayın! Bu soruyu 2011'de Android'de şu anda olduğumdan çok daha az deneyimli olduğum zaman yanıtladım. Yukarıdaki cevabım yanıltıcı ve yanlış kabul ediliyor. Onu orada bırakıyorum çünkü birçok insan beni düzeltmek için aşağıya yorum yaptı ve dersimi öğrendim.

Bu konuda çok daha iyi başka cevaplar var, ama en azından bana daha doğru cevap vereceğim. Normal bir Java kullanmanın yanlış bir yanı yoktur Thread; ancak, nasıl uyguladığınıza gerçekten dikkat etmelisiniz, çünkü yanlış yapmak çok işlemci yoğun olabilir (en dikkat çekici semptom cihazınızın ısınması olabilir). AsyncTasks, arka planda çalıştırmak istediğiniz çoğu görev için oldukça idealdir (yaygın örnekler disk G / Ç, ağ aramaları ve veritabanı aramalarıdır). Ancak, AsyncTaskkullanıcı uygulamanızı kapattıktan veya cihazını beklemeye aldıktan sonra devam etmesi gerekebilecek özellikle uzun işlemler için kullanılmamalıdır. Çoğu durumda, UI iş parçacığına ait olmayan herhangi bir şey, bir AsyncTask.


teşekkürler, aslında AsyncTasks yerine Threads kullanmalıyım bir nedeni var mı? Yoksa bundan faydalanmak daha mı tavsiye edilir?
Alx

9
@AeroDroid Örneğinizde: "basit bir while (true)", döngüde bir uyku durumu eklemediğiniz sürece CPU'yu burada sabitleyeceksiniz. Bu sonsuz döngü için geçerlidir. Bu ek yük nedeniyle CPU kullanımını azaltmak istiyorsanız, iş parçacığının sonunda ipliği birkaç milisaniye kadar uyuyun.
Hata 454

1
Hata 454 - bu ilginç! Uyku süresi için uygun bir sayı seçmek zorunda olsaydınız, 40-80 milisaniye arasında mı olurdu?
Abhijit

6
@Abhijit SDL'de yaptığım oyunlardan, döngüye 10 ms'lik bir uyku eklemek, boşta kalma durumlarında% 99 cpu'dan ~ 0'a düşmek için yeterliydi.
Hata 454

15
Aslında developer.android.com/reference/android/os/AsyncTask.html diyor ki: "AsyncTasks, KISA işlemler için ideal olarak kullanılmalıdır". Bunları dikkatli bir şekilde kullanmalısınız, çünkü sistem tarafından çalıştırılmadan işten çıkarılabilirler!
type-a1pha

5

AsyncTaskarka planda yapılması gereken birkaç saniyeden fazla işlem yapmak üzere tasarlanmıştır (sunucudan megabayt dosya indirme veya dosya GÇ işlemleri gibi işlem yoğun işlem gerektiren işlemler için önerilmez). Uzun süren bir işlem yürütmeniz gerekiyorsa, java yerel iş parçacıklarını kullanmanız önemle tavsiye edilir. Java, ihtiyacınız olanı yapmak için çeşitli iş parçacığıyla ilgili sınıflar verir. HandlerUI İş Parçacığını güncellemek için kullanın .


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();
    }

}

1

Burada bir örnekle soruyu cevaplamaya çalışayım :) - MyImageSearch [Lütfen ana etkinlik ekranının görüntüsüne bakın - metin düzenleme / arama düğmesi / ızgara görünümü içeren]

MyImageSearch

MyImageSearch açıklaması - Kullanıcı metin düzenleme alanına ayrıntıları girdikten ve arama düğmesine tıkladıktan sonra, flickr tarafından sağlanan web hizmetleri üzerinden internette görüntü arayacağız (sadece bir anahtar / gizli belirteç almak için oraya kaydolmanız gerekir) - arama için, daha sonra ızgara görünümünü yüklemek için kullanacağımız tek tek resimlerin URL'lerini içeren yanıt olarak bir HTTP İsteği ve GET JSON Verisi göndeririz.

Uygulamam - Ana etkinlikte, AsyncTask'ı doInBackGround Yönteminde HTTP İsteğini göndermek ve JSON Yanıtını almak ve FlickrAdapter aracılığıyla GridView'umu güncellemek için kullanacağım yerel ArrayList'imi güncellemek için genişleten bir iç sınıf tanımlayacağım (BaseAdapter'ı genişletir) ve ızgara görünümünü yeniden yüklemek için AsyncTask öğesinin onPostExecute () öğesindeki adaptor.notifyDataSetChanged () öğesini çağırın. Burada HTTP İsteğinin, AsyncTask aracılığıyla yaptığım bir engelleme çağrısı olduğunu unutmayın. Performansı artırmak veya SDCard'da saklamak için adaptördeki öğeleri önbelleğe alabilirim. FlickrAdapter içinde şişireceğim ızgara benim uygulamada bir ilerleme çubuğu ve görüntü görünümü içerir. Aşağıda kullandığım mainActivity kodunu bulabilirsiniz.

Şimdi Sorunun Cevabı - Bu yüzden, tek tek Görüntüler almak için JSON verilerine sahip olduktan sonra, işleyicileri veya Konuları veya AsyncTask aracılığıyla görüntüleri arka planda alma mantığını uygulayabiliriz. Burada, indirdiğim görüntülerimin kullanıcı arayüzünde / ana iş parçacığında görüntülenmesi gerektiğinden, içeriğe erişimi olmadığı için iş parçacıklarını olduğu gibi kullanamayacağımızı not etmeliyiz. FlickrAdapter'te düşünebileceğim seçenekler:

  • Seçenek 1: Bir LooperThread oluşturun [iş parçacığını genişletir] - ve bu iş parçacığını açık tutarak görüntüleri bir iş parçacığında sırayla indirmeye devam edin [looper.loop ()]
  • Seçim 2: Bir iş parçacığı havuzu kullanın ve benim ImageView başvuru içeren myHandler aracılığıyla çalıştırılabilir gönderin, ancak Izgara görünümünde görünümleri geri dönüştürülmüş olduğundan, yine dizin 4'te görüntü dizin 9 [download olabilir nerede sorun ortaya çıkabilir daha fazla zaman ayırın]
  • Seçenek 3 [Bunu kullandım]: Bir İş Parçacığı Havuzu kullanın ve ImageH'nin dizini ve ImageView'in kendisi ile ilgili veriler içeren myHandler'e bir mesaj gönderin, bu nedenle handleMessage () yaparken ImageView'i yalnızca currentIndex diziniyle eşleşirse güncelleyeceğiz indirmeye çalıştığımız Görüntü.
  • Seçim 4: AsyncTask'ı arka planda görüntüleri indirmek için kullanın, ancak burada iplik havuzunda istediğim iş parçacığı sayısına erişemeyeceğim ve farklı android sürümüne göre değişebilir, ancak Seçim 3'te bilinçli karar verebilirim kullanılan aygıt yapılandırmasına bağlı olarak iş parçacığı havuzu boyutunda.

İşte kaynak kodu:

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);
    }
}

Umarım cevabım uzun olsa da daha ince ayrıntıları anlamaya yardımcı olur.


Analoji uğruna bir örneğe dayanan açıklamamın neden aşağıya indirildiğini öğrenebilir miyim, böylece ondan da öğrenebilirim?
akshaymani

2
her şeyden önce cevabınız için teşekkürler, bu konu biraz eski olmasına rağmen temel kavramlar hala güncelliğini korumaktadır. İlk sorum hiç yanıtlanmadı, bir örnek veriyorsunuz ve nasıl çalıştığını açıklıyorsunuz, ancak sorular işleyici, asenkronize ve iş parçacığı arasındaki farkları soruyor.
Alx

@ 80yaprakları tamam şimdi anladım, bir yoldan diğerine seçme sonucuna nasıl geldiğimi açıklamaya çalıştım. Her neyse, yazdıklarımın doğru olup olmadığı veya daha da geliştirilip geliştirilemeyeceği konusunda başkalarının görüşlerini duymak isteriz.
akshaymani

1

Hangisini seçmeniz gerektiğine bağlıdır.

İşleyici çoğunlukla diğer iş parçacığından ana iş parçacığına geçmek için kullanılır, işleyici çalıştırılabilir görevini kuyrukta yayınladığı bir ilmek yapıcıya bağlanır. Yani zaten başka bir iş parçacığındaysanız ve ana iş parçacığına geçerseniz, zaman uyumsuz görev veya başka iş parçacığı yerine tutamağa ihtiyacınız vardır.

Bir ilmek yapıcı olmayan ana iş parçacığı dışında oluşturulan İşleyici, iş parçacığı oluşturuldukça hata vermezse, bu iş parçacığının bir durdurucu yapılması gerekir

AsyncTask , arka plan iş parçacığında çalışan ve sonucunu ana iş parçacığına veren birkaç saniye boyunca kod yürütmek için kullanılır ** * AsyncTask Sınırlamaları 1. Async Görev, faaliyetin yaşam döngüsüne bağlı değildir ve yükleyici yokken etkinliği yok olsa bile çalışmaya devam eder Bu sınırlamaya sahip değilsiniz 2. Tüm Async Görevleri, yürütme için aynı arka plan iş parçacığını paylaşır ve bu da uygulama performansını etkiler

İş parçacığı da arka plan çalışması için uygulamada kullanılır, ancak ana iş parçacığında geri arama yoktur. Gereksinim bir iş parçacığı yerine bazı iş parçacığı yerine ve birçok kez görev vermesi gerekiyorsa iş parçacığı havuzu yürütücüsü daha iyi bir seçenektir.Eg Kayma gibi birden çok url'den Görüntü yükleme gereksinimi.


0

Konu

Bir uygulamayı başlattığınızda, kodu yürütmek için bir işlem oluşturulur. Bilgi işlem kaynağını verimli bir şekilde kullanmak için, iş parçacıkları süreç içinde başlatılabilir, böylece aynı anda birden çok görev yürütülebilir. Böylece iş parçacıkları, işlemciyi boş zaman olmadan verimli bir şekilde kullanarak verimli uygulamalar oluşturmanıza olanak tanır.

Android'de, tüm bileşenler ana iş parçacığı adı verilen tek bir işlemde yürütülür. Android sistem kuyruk görevleri ve ana iş parçacığı üzerinde tek tek yürütmek. Uzun süren görevler yürütüldüğünde uygulama yanıt vermiyor.

Bunu önlemek için, çalışan iş parçacıkları oluşturabilir ve arka plan veya uzun süren görevleri çalıştırabilirsiniz.

Handler

Android tek iş parçacığı modeli kullandığından, UI bileşenleri iş parçacığı için güvenli değil, yalnızca oluşturduğu iş parçacığının bunlara erişmesi anlamına gelir, bu da UI bileşeninin yalnızca ana iş parçacığında güncellenmesi gerektiği anlamına gelir. Kullanıcı arabirimi bileşeni ana iş parçacığında çalıştığından, çalışan iş parçacıkları üzerinde çalışan görevler kullanıcı arabirimi bileşenlerini değiştiremez. İşte burada Handler devreye giriyor. Looper'ın yardımıyla işleyici, yeni iş parçacığına veya mevcut iş parçacığına bağlanabilir ve bağlı iş parçacığında içerdiği kodu çalıştırabilir.

İşleyici, dişler arası iletişimi mümkün kılar. İşleyici kullanarak, arka plan iş parçacığı sonuçları gönderebilir ve ana iş parçacığına bağlı işleyici ana iş parçacığındaki UI bileşenlerini güncelleyebilir.

AsyncTask

Android tarafından sağlanan AsyncTask, arka planda basit görevleri çalıştırmak ve arka plan iş parçacığından ana iş parçacığına kadar sonuçları güncellemek için hem iş parçacığı hem de işleyici kullanır.

Örnekler için lütfen android iş parçacığı, işleyici, asynctask ve iş parçacığı havuzlarına bakın.


-1

Handler- dişler arasındaki iletişim ortamıdır. Android'de çoğunlukla işleyici aracılığıyla mesaj oluşturarak ve göndererek ana iş parçacığı ile iletişim kurmak için kullanılır

AsyncTask- arka plan iş parçacığında uzun süre çalışan uygulamaları gerçekleştirmek için kullanılır. N ile AsyncTaskişlemi bir arka plan iş parçacığında yapabilir ve uygulamanın ana iş parçacığında sonucu alabilirsiniz.

Thread- eşzamanlılık ve maksimum işlemci kullanımı için hafif bir işlemdir. Android'de, uygulamanın kullanıcı arayüzüne dokunmayan etkinlikleri gerçekleştirmek için iş parçacığını kullanabilirsiniz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.