Looper'ın amacı nedir ve nasıl kullanılır?


454

Android'de yeniyim. LooperSınıfın ne yaptığını ve nasıl kullanılacağını bilmek istiyorum . Android Looper sınıfı belgelerini okudum ancak tam olarak anlayamıyorum. Bunu birçok yerde gördüm ama amacını anlayamadım. Herkes amacını tanımlayarak ve Loopermümkünse basit bir örnek vererek bana yardımcı olabilir mi?


7
Az önce Looper'ın ve Safari Books Online'da kullanımının olağanüstü ayrıntılı ve net bir açıklamasını buldum. Ne yazık ki, yalnızca sınırlı bir süre için erişim ücretsiz olduğundan şüpheleniyorum. safaribooksonline.com/library/view/efficient-android-threading/…
Joe Lapp

1
Android makaleleri ve referans sayfaları, mevcut makaleyi kavrayabilmeniz için önceki bir makaleye sahip olmanızı ve anlamanız gerektiğini gerektirir. Api kılavuzlarındaki Etkinlik ve Hizmet makalelerini okumanızı ve sonra İşleyici ve İlmek Yapıcı'yı okumanızı öneririm. Ayrıca bir iş parçacığının ne olduğunu anlamanıza yardımcı olur (bir android iş parçacığı değil, genel olarak bir iş parçacığı ... örneğin POSIX).
FutureSci

1
Bu makaleyi yararlı buldum: codetheory.in/…
Herman

Yanıtlar:


396

Lüper nedir?

Lüper, bir kuyruktaki İletileri (Çalıştırılabilirler) yürütmek için kullanılan bir sınıftır. Normal iş parçacığı böyle bir sıraya sahip değildir, örneğin basit iş parçacığı herhangi bir kuyruğa sahip değildir. Bir kez yürütülür ve yöntem yürütme bittikten sonra, iş parçacığı başka bir ileti (Runnable) çalıştırmaz.

Looper sınıfını nerede kullanabiliriz?

Birisi birden fazla ileti (Runnables) yürütmek istiyorsa, iş parçacığında kuyruk oluşturmaktan sorumlu olan Looper sınıfını kullanmalıdır. Örneğin, internetten dosya indiren bir uygulama yazarken, indirilecek dosyaları sıraya koymak için Looper sınıfını kullanabiliriz.

Nasıl çalışır?

prepare()İlmek Yapıcı hazırlamak için bir yöntem vardır . Ardından loop()geçerli iş parçacığında bir ileti döngüsü oluşturmak için yöntemi kullanabilirsiniz ve şimdi Looper'ınız döngüden çıkıncaya kadar kuyruktaki istekleri yürütmeye hazırdır.

İşte Lüper'i hazırlayabileceğiniz kod.

class LooperThread extends Thread {
      public Handler mHandler;

      @Override
      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              @Override
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

17
AsyncTask bu amaç için daha iyidir ve tüm iş parçacığı yönetimini kapsadığı için daha az karmaşıktır.
Fernando Gallego

4
Run () ve handleMessage () yöntemlerinden önce @Override ek açıklamaları olmalıdır
Andrew Mackenzie

5
Belgeler looper.quit'i aramanız gerektiğini belirtir. Yukarıdaki kodunuzda, Looper.loop süresiz olarak engellenecektir.
AndroidDev

2
Bir döngüden nasıl çıkılır. Yukarıdaki kod örneğine Looper.quit () eklemek nerede?
Seenu69

6
Bir lüper ile bir iş parçacığı için uygun bir sınıf olan HandlerThread kullanmak daha iyi olacağını düşünüyorum .
Nimrod Dayan

287

Looper'ın GUI çerçevesi bağlamında ne olduğunu daha iyi anlayabilirsiniz. Lüper 2 şey yapmak için yapılır.

1) Looper , run () yöntemi döndüğünde sona eren normal bir iş parçacığını , Android uygulaması çalışana kadar sürekli çalışan bir şeye dönüştürür , bu da GUI çerçevesinde gereklidir (Teknik olarak, run () yöntemi geri döndüğünde hala sona erer. aşağıda ne demek istediğimi netleştirin).

2) Looper , GUI çerçevesinde de yapılması gereken işlerin sıralandığı bir kuyruk sağlar .

Bildiğiniz gibi, bir uygulama başlatıldığında, sistem uygulama için "ana" olarak adlandırılan bir yürütme dizisi oluşturur ve Android uygulamaları normalde varsayılan olarak "ana iş parçacığı" olarak tek bir iş parçacığında çalışır. Ancak ana iplik bazı gizli, özel iplik değildir . Bu sadece new Thread()kod ile oluşturduğunuz iş parçacıklarına benzer normal bir iş parçacığıdır , yani run () yöntemi döndüğünde sonlandırılır! Aşağıdaki örneği düşünün.

public class HelloRunnable implements Runnable {
    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }
}

Şimdi bu basit prensibi Android uygulamalarına uygulayalım. Bir Android uygulaması normal iş parçacığında çalışırsa ne olur? "Ana" veya "Kullanıcı Arayüzü" olarak adlandırılan bir iş parçacığı veya uygulamanızı başlatan her şey ve tüm kullanıcı arayüzünü çizer. Böylece, ilk ekran kullanıcılara gösterilir. Peki şimdi ne olacak? Ana iş parçacığı sonlandırılıyor mu? Hayır, olmamalı. Kullanıcılar bir şeyler yapmayı beklemeli, değil mi? Fakat bu davranışı nasıl başarabiliriz? İle deneyebiliriz Object.wait()veyaThread.sleep(). Örneğin, ana iş parçacığı ilk ekranı görüntülemek için ilk işini bitirir ve uyur. Uyanır, yani yapılacak yeni bir iş getirildiğinde kesintiye uğramak anlamına gelir. Şimdiye kadar çok iyi, ama şu anda birden fazla işi tutmak için kuyruk benzeri bir veri yapısına ihtiyacımız var. Bir kullanıcının ekrana seri olarak dokunduğu ve bir görevin tamamlanması daha uzun sürdüğü bir durumu düşünün. Bu nedenle, yapılacak işleri ilk giren ilk çıkar yolunda tutabilmek için bir veri yapısına ihtiyacımız var. Ayrıca, kesme kullanarak sürekli çalışan ve işlenen iş geldiğinde iş parçacığının uygulanmasının kolay olmadığını ve karmaşık ve çoğu zaman sürdürülemez koda yol açtığını hayal edebilirsiniz. Böyle bir amaç için yeni bir mekanizma oluşturmayı tercih ediyoruz ve Looper'ın konusu bu . Looper sınıfının resmi belge"Varsayılan olarak iş parçacıklarının kendileriyle ilişkili bir mesaj döngüsü yoktur" ve Looper "bir iş parçacığı için bir mesaj döngüsü çalıştırmak için kullanılan bir sınıftır". Şimdi bunun ne anlama geldiğini anlayabilirsiniz.

İşleri daha net hale getirmek için, ana iş parçacığının dönüştürüldüğü kodu kontrol edelim. Her şey ActivityThread sınıfında olur . Main () yönteminde, normal bir ana iş parçasını ihtiyacımız olan bir şeye dönüştüren aşağıdaki kodu bulabilirsiniz.

public final class ActivityThread {
    ...
    public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
        Looper.loop();
        ...
    }
}

ve Looper.loop()yöntem sonsuz döngü ve bir mesajı ayıklayın ve birer birer işleyin:

public static void loop() {
    ...
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        ...
        msg.target.dispatchMessage(msg);
        ...
    }
}

Yani, temelde Looper GUI çerçevesinde oluşan bir problemi çözmek için yapılmış bir sınıftır. Ancak bu tür ihtiyaçlar başka durumlarda da ortaya çıkabilir. Aslında çok iş parçacığı uygulaması için oldukça ünlü bir desen ve Doug Lea tarafından " Java Eşzamanlı Programlama " (Daha, Bölüm 4.1.4 "İşçi Konu" yararlı olacaktır) hakkında daha fazla bilgi edinebilirsiniz . Ayrıca, bu tür bir mekanizmanın Android çerçevesinde benzersiz olmadığını hayal edebilirsiniz, ancak tüm GUI çerçevesinin buna biraz benzemesi gerekebilir. Java Swing çerçevesinde neredeyse aynı mekanizmayı bulabilirsiniz.


26
Looper sınıfının neden kullanılacağı hakkında her şeyi açıklayan tek cevap budur. Neden en iyi cevap olmadığından emin değilim, üç yüksek puanlı cevap hiçbir şeyi açıklamıyor.
Andrew Koster

4
@AK. Bu yüzden bu cevabı çok geç görünse bile ekledim. Cevabımın sana yardım ettiğine sevindim! :)
김준호

1
@ Hey-men-whatsup Evet
김준호

1
Bunu okumadan önce "Lüper ???" ve şimdi "Ah evet, hadi tartışalım". Thanks man, great answer :)
umerk44

Hızlı soru. Ana iş parçacığında, tüm UI öğelerini çıkardıktan sonra uykuya daldığını belirttiniz. Ancak diyelim ki kullanıcı ekrandaki bir düğmeyle etkileşime giriyor, bu düğme tıklaması ana kuyruğa bile konmuyor, daha sonra bazı nesneler onu doğru etkinliğe gönderecek, sonra o etkinliğin ana iş parçacığı uyanık ve yürütecek o düğme tıklaması için geri arama kodu?
CapturedTree

76

Lüper, görevlerin tek bir iş parçacığında sıralı olarak yürütülmesine izin verir. Ve işleyici, yürütmemiz gereken görevleri tanımlar. Bu örnekte göstermeye çalıştığım tipik bir senaryo:

class SampleLooper extends Thread {
@Override
public void run() {
  try {
    // preparing a looper on current thread     
    // the current thread is being detected implicitly
    Looper.prepare();

    // now, the handler will automatically bind to the
    // Looper that is attached to the current thread
    // You don't need to specify the Looper explicitly
    handler = new Handler();

    // After the following line the thread will start
    // running the message loop and will not normally
    // exit the loop unless a problem happens or you
    // quit() the looper (see below)
    Looper.loop();
  } catch (Throwable t) {
    Log.e(TAG, "halted due to an error", t);
  } 
}
}

Şimdi, görevi yürütmek için Looper'a göndermek için işleyiciyi başka bazı iş parçacıklarında da (ui iş parçacığı gibi) kullanabiliriz.

handler.post(new Runnable()
{
public void run() {
//This will be executed on thread using Looper.
    }
});

UI iş parçacığında, ui iş parçacığında iletileri işlememize izin veren örtülü bir Looper var.


herhangi bir kullanıcı arayüzü sürecini kilitlemeyecek, doğru mu?
2015

4
Sıraya "iş" göndermek için nasıl örnek
eklediğiniz

Bu, kişinin neden bu sınıfı kullanacağını açıklamaz, sadece nasıl kullanacağını açıklar.
Andrew Koster

33

Android Loopertakmak için bir sarıcı MessageQueueiçin Threadve Kuyruk işleme yönetir. Android belgelerinde çok şifreli görünüyor ve çoğu zaman Looperilgili UI erişim sorunlarıyla karşılaşabiliriz. Temelleri anlamıyorsak, ele almak çok zorlaşır.

İşte bir olan makale açıklar Looperonu ve kullanımını nasıl kullanılacağı, yaşam döngüsünü LooperiçindeHandler

resim açıklamasını buraya girin

Lüper = Konu + MessageQueue


3
Bu, kişinin neden bu sınıfı kullanacağını açıklamaz, sadece nasıl kullanacağını açıklar.
Andrew Koster

14

Looper & Handler Tanımı:

Lüper , bir iş parçacığını Boru Hattı İş Parçacığına dönüştüren bir sınıftır ve İşleyici , görevleri başka herhangi bir iş parçacığından içeri aktarmanız için bir mekanizma sağlar.

Detaylar:

Bu yüzden PipeLine İş Parçacığı , bir İşleyici aracılığıyla diğer iş parçacıklarından daha fazla görevi kabul edebilen bir iş parçacığıdır.

Looper onu çalıştırır, sonraki görevi alır sonra bir sonrakini ve benzeri alır - bu döngü uygulayan çünkü böyle adlandırılmıştır. İşleyiciye işleyici denir, çünkü her seferinde başka bir iş parçasından bir sonraki görevi işlemek veya kabul etmek ve Looper'a (İş Parçacığı veya PipeLine İş Parçacığı) geçmek için kullanılır.

Misal:

Bir Looper ve Handler veya PipeLine İş Parçacığının en mükemmel örneği, arka planda her ağ çağrısı için yeni bir İş Parçacığı başlatmak yerine, birden fazla görüntü indirmek veya tek bir iş parçacığında tek tek bir iş parçacığına (Http) yüklemek.

Looper ve Handler ve Pipeline'ın tanımı hakkında daha fazla bilgiyi buradan okuyun:

Android Bağırsakları: Döngülere ve İşleyicilere Giriş


7

Bir Lüper , synchronized MessageQueuekuyruğa yerleştirilmiş Mesajları işlemek için kullanılana sahiptir.

ThreadBelirli bir Depolama Deseni uygular .

Sadece bir Looperbaşına Thread. Anahtar yöntemler arasında prepare(), loop()ve quit().

prepare()akımı a Threadolarak başlatır Looper. prepare()olduğu statickullanan bir yöntem ThreadLocal, aşağıda gösterildiği gibi bir sınıf.

   public static void prepare(){
       ...
       sThreadLocal.set
       (new Looper());
   }
  1. prepare() olay döngüsünü çalıştırmadan önce açıkça çağrılmalıdır.
  2. loop()İletilerin belirli bir İleti dizisinin ileti sırasına ulaşmasını bekleyen olay döngüsünü çalıştırır. Sonraki İleti alındıktan sonra, loop()yöntem İletiyi hedef işleyicisine gönderir
  3. quit()olay döngüsünü kapatır. Döngüyü sonlandırmaz, bunun yerine özel bir mesaj atar

LooperThreadbirkaç adımda programlanabilir

  1. uzatmak Thread

  2. İş Looper.prepare()parçacığını birLooper

  3. HandlerGelen mesajları işlemek için bir veya daha fazla mesaj oluşturun

  4. Looper.loop()Döngü söylenene kadar mesajları işlemek için arayın quit().

5

Java iş parçacığının ömrü , run()yöntem tamamlandıktan sonra sona erdi . Aynı konu tekrar başlatılamaz.

Lüper normal Threadbir mesaj döngüsüne dönüşür. Anahtar yöntemler Looperşunlardır:

void prepare ()

Geçerli iş parçacığını lüper olarak başlatın. Bu, döngüye başlamadan önce bu lüpere referans veren işleyiciler oluşturma şansı verir. Bu yöntemi çağırdıktan sonra loop () yöntemini çağırdığınızdan emin olun ve quit () yöntemini çağırarak işlemi sonlandırın.

void loop ()

Bu iş parçacığında ileti sırasını çalıştırın. Döngüyü sonlandırmak için quit () öğesini çağırdığınızdan emin olun.

void quit()

Lüperden çıkar.

Loop () yönteminin, ileti kuyruğunda başka ileti işlemeden sonlandırılmasına neden olur.

Janishar'ın bu mindorks makalesi , temel kavramları güzel bir şekilde açıklıyor.

resim açıklamasını buraya girin

Looperbir Konu ile ilişkilendirilir. LooperUI iş parçacığına ihtiyacınız varsa , Looper.getMainLooper()ilişkili iş parçacığı döndürür.

LooperBir İşleyici ile ilişkilendirilmiş olmanız gerekir .

Looper,, Handlerve HandlerThreadAndroid'in asenkron programlama sorunlarını çözme yoludur.

Sahip olduktan sonra Handleraşağıdaki API'ları arayabilirsiniz.

post (Runnable r)

Çalıştırılabilir r'nin ileti kuyruğuna eklenmesine neden olur. Çalıştırılabilir bu işleyicinin bağlı olduğu iş parçacığında çalıştırılır.

boolean sendMessage (Message msg)

Geçerli saatten önce bekleyen tüm iletilerden sonra bir iletiyi ileti kuyruğunun sonuna iter. Bu işleyiciye eklenmiş iş parçacığında handleMessage (İleti) içinde alınır.

HandlerThread bir lüper olan yeni bir iş parçacığı başlatmak için kullanışlı bir sınıftır. İlmek yapıcı daha sonra işleyici sınıfları oluşturmak için kullanılabilir

Bazı senaryolarda, RunnableUI İş Parçacığında görevleri çalıştıramazsınız . Örn. Ağ işlemleri: Bir sokete mesaj gönderin, bir URL açın ve okuyarak içerik alınInputStream

Bu durumlarda HandlerThreadyararlıdır. LooperNesneyi alabilir HandlerThreadve ana iş parçacığı yerine bir Handleraçık oluşturabilirsiniz HandlerThread.

HandlerThread kodu şöyle olacaktır:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

Örnek kod için aşağıdaki gönderiye bakın:

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


5

Lüper İpliklerini Anlama

Java run () yönteminde bir görevi gerçekleştirmek ve bundan sonra sona ermek üzere tasarlanmış bir yürütme birimine iş parçacığı ekleyin: resim açıklamasını buraya girin

Ancak Android'de bir Konuyu canlı tutmamız ve örneğin kullanıcı girişlerini / etkinliklerini beklememiz gereken birçok kullanım durumu vardır. UI iş parçacığı aka Main Thread.

Android'deki ana iş parçacığı, ilk olarak bir uygulamanın başlangıcında JVM tarafından başlatılan ve kullanıcı onu kapatmayı veya işlenmeyen bir istisna ile karşılaşana kadar çalışmaya devam eden bir Java iş parçacığıdır.

Bir uygulama başlatıldığında, sistem uygulama için "ana" adlı bir yürütme dizisi oluşturur. Bu iş parçacığı çok önemlidir çünkü olayları çizim olayları da dahil olmak üzere uygun kullanıcı arabirimi widget'larına göndermekten sorumludur.

resim açıklamasını buraya girin

Şimdi burada ana iş parçacığı Java iş parçacığı olmasına rağmen nokta kullanıcı olaylarını dinlemeye devam ediyor ve ekranda 60 fps kare çiziyor ve yine de her döngüden sonra ölmeyecek. bu nasıl

Cevap Looper Sınıfıdır : Looper bir iş parçacığını canlı tutmak ve o iş parçacığında görevleri yürütmek için bir mesaj kuyruğunu yönetmek için kullanılan bir sınıftır.

Varsayılan olarak, iş parçacıklarının kendileriyle ilişkilendirilmiş bir ileti döngüsü yoktur, ancak çalıştırma yönteminde Looper.prepare () öğesini çağırarak ve sonra Looper.loop () öğesini çağırarak bir ileti döngüsü atayabilirsiniz.

Lüper'in amacı, bir İş Parçasını canlı tutmak ve Messageilk yürütme döngüsünden sonra yok edilecek hesaplama yapmak için giriş nesnesinin bir sonraki döngüsünü beklemektir .

Looper'ın Messagenesne kuyruğunu nasıl yönettiğini daha derinlemesine incelemek istiyorsanız, kaynak koduna göz atabilirsiniz Looperclass:

https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/os/Looper.java

Aşağıda, kullanarak bir sınıf oluşturup sınıfla nasıl Looper Threadiletişim kurabileceğinize ilişkin bir örnek verilmiştir.ActivityLocalBroadcast

class LooperThread : Thread() {

    // sendMessage success result on UI
    private fun sendServerResult(result: String) {
        val resultIntent = Intent(ServerService.ACTION)
        resultIntent.putExtra(ServerService.RESULT_CODE, Activity.RESULT_OK)
        resultIntent.putExtra(ServerService.RESULT_VALUE, result)
        LocalBroadcastManager.getInstance(AppController.getAppController()).sendBroadcast(resultIntent)
    }

    override fun run() {
        val looperIsNotPreparedInCurrentThread = Looper.myLooper() == null

        // Prepare Looper if not already prepared
        if (looperIsNotPreparedInCurrentThread) {
            Looper.prepare()
        }

        // Create a handler to handle messaged from Activity
        handler = Handler(Handler.Callback { message ->
            // Messages sent to Looper thread will be visible here
            Log.e(TAG, "Received Message" + message.data.toString())

            //message from Activity
            val result = message.data.getString(MainActivity.BUNDLE_KEY)

            // Send Result Back to activity
            sendServerResult(result)
            true
        })

        // Keep on looping till new messages arrive
        if (looperIsNotPreparedInCurrentThread) {
            Looper.loop()
        }
    }

    //Create and send a new  message to looper
    fun sendMessage(messageToSend: String) {
        //Create and post a new message to handler
        handler!!.sendMessage(createMessage(messageToSend))
    }


    // Bundle Data in message object
    private fun createMessage(messageToSend: String): Message {
        val message = Message()
        val bundle = Bundle()
        bundle.putString(MainActivity.BUNDLE_KEY, messageToSend)
        message.data = bundle
        return message
    }

    companion object {
        var handler: Handler? = null // in Android Handler should be static or leaks might occur
        private val TAG = javaClass.simpleName

    }
}

Kullanımı :

 class MainActivity : AppCompatActivity() {

    private var looperThread: LooperThread? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // start looper thread
        startLooperThread()

        // Send messages to Looper Thread
        sendMessage.setOnClickListener {

            // send random messages to looper thread
            val messageToSend = "" + Math.random()

            // post message
            looperThread!!.sendMessage(messageToSend)

        }   
    }

    override fun onResume() {
        super.onResume()

        //Register to Server Service callback
        val filterServer = IntentFilter(ServerService.ACTION)
        LocalBroadcastManager.getInstance(this).registerReceiver(serverReceiver, filterServer)

    }

    override fun onPause() {
        super.onPause()

        //Stop Server service callbacks
     LocalBroadcastManager.getInstance(this).unregisterReceiver(serverReceiver)
    }


    // Define the callback for what to do when data is received
    private val serverReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val resultCode = intent.getIntExtra(ServerService.RESULT_CODE, Activity.RESULT_CANCELED)
            if (resultCode == Activity.RESULT_OK) {
                val resultValue = intent.getStringExtra(ServerService.RESULT_VALUE)
                Log.e(MainActivity.TAG, "Server result : $resultValue")

                serverOutput.text =
                        (serverOutput.text.toString()
                                + "\n"
                                + "Received : " + resultValue)

                serverScrollView.post( { serverScrollView.fullScroll(View.FOCUS_DOWN) })
            }
        }
    }

    private fun startLooperThread() {

        // create and start a new LooperThread
        looperThread = LooperThread()
        looperThread!!.name = "Main Looper Thread"
        looperThread!!.start()

    }

    companion object {
        val BUNDLE_KEY = "handlerMsgBundle"
        private val TAG = javaClass.simpleName
    }
}

Bunun yerine Async görevini veya Intent Services'ı kullanabilir miyiz?

  • Zaman uyumsuz görevler, arka planda kısa bir işlem gerçekleştirmek ve kullanıcı arabirimi iş parçacığında ilerleme ve sonuçlar vermek üzere tasarlanmıştır. Async görevlerinin 128'den fazla Async görevi oluşturamayacağınız gibi sınırları vardır ve ThreadPoolExecutoryalnızca en fazla 5 Async görevine izin verir .

  • IntentServicesayrıca arka plan görevini biraz daha uzun süre yapmak için tasarlanmıştır ve LocalBroadcastiletişim kurmak için kullanabilirsiniz Activity. Ancak görev yürütüldükten sonra hizmetler imha edilir. Eğer uzun süre çalışmaya devam etmek istiyorsanız, sizin gibi kontroller yapmanız gerekir while(true){...}.

Looper Konu için diğer anlamlı kullanım durumları:

  • Sunucunun İstemci soketini dinlemeye devam ettiği ve onay yazdığı 2 yönlü soket iletişimi için kullanılır

  • Arka planda bitmap işleme. Görüntü URL'sini Looper iş parçacığına geçirin, filtre efektleri uygular ve tempe rory konumunda saklar ve ardından görüntünün geçici yolunu yayınlar.


4

Bu cevabın soru ile ilgisi yoktur, ancak lüper kullanımı ve insanların TÜM'de işleyici ve lüper oluşturma şekli, buradaki cevaplar düz kötü bir uygulamadır (bazı açıklamalar doğru olsa da), bunu göndermeliyim:

HandlerThread thread = new HandlerThread(threadName);
thread.start();
Looper looper = thread.getLooper();
Handler myHandler = new Handler(looper);

ve tam bir uygulama için


3

Bir Hizmette birden çok aşağı indirme veya yükleme öğesi daha iyi bir örnektir.

Handlerve AsnycTaskgenellikle Olayları / İletileri kullanıcı arayüzü (iş parçacığı) ile çalışan iş parçacığı arasında yaymak veya eylemleri geciktirmek için kullanılır. Bu yüzden daha çok kullanıcı arayüzü ile ilgilidir.

Bir kullanıcı etkileşimi veya görüntülenen bir kullanıcı arayüzü olmasa bile (arka plandaki bir iş parçacığı ile ilgili kuyrukta) Loopergörevleri ( Çalıştırılabilirler, Vadeli İşlemler ) işler ( arama sırasında arka planda bir dosya indirir).


1

Lüper nedir?

DOKTORLARDAN

Looper

LooperBir thread. İçin bir ileti döngüsü çalıştırmak için kullanılan sınıf . Varsayılan olarak, iş parçacıklarının kendileriyle ilişkili bir mesaj döngüsü yoktur; bir tane oluşturmak prepare()için, döngüyü çalıştıracak olan iş parçacığını çağırın ve döngü loop()duruncaya kadar iletileri işlemesini sağlamak için.

  • A Looperbir mesaj işleme döngüsüdür:
  • Looper'ın önemli bir karakteri, Looper'ın oluşturulduğu iplikle ilişkili olmasıdır.
  • Looper sınıfı MessageQueue, bir liste mesajı içeren a'yı korur . Looper'ın önemli bir karakteri, Looper'ın oluşturulduğu iplikle ilişkili olmasıdır.
  • Bu Looper, döngüyü uyguladığı için adlandırılır - bir sonraki görevi alır, yürütür, sonra bir sonrakini alır vb. HandlerBirisi daha iyi bir isim icat edemedi çünkü bir işleyici denir
  • Android Looper, Android kullanıcı arabirimi içinde, Düğme tıklamaları, ekran yeniden çizimleri ve yönlendirme anahtarları gibi UI olaylarını işlemek için Handler sınıfıyla birlikte bir Java sınıfıdır.

Nasıl çalışır?

resim açıklamasını buraya girin

Lüper Oluşturma

Bir iş parçacığı alır Looperve çalıştıktan sonra MessageQueuearayarak Looper.prepare(). Looper.prepare()çağıran evreyi tanımlar, bir Lüper ve MessageQueuenesne oluşturur ve evreyi ilişkilendirir

BASİT KOD

class MyLooperThread extends Thread {

      public Handler mHandler; 

      public void run() { 

          // preparing a looper on current thread  
          Looper.prepare();

          mHandler = new Handler() { 
              public void handleMessage(Message msg) { 
                 // process incoming messages here
                 // this will run in non-ui/background thread
              } 
          }; 

          Looper.loop();
      } 
  }

Daha fazla bilgi için aşağıdaki gönderiyi kontrol edin


mükemmel, mekaniği anladım. teşekkürler
Serg Burlaka
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.