Android 開(kāi)發(fā)之Handler

談到Android開(kāi)發(fā),就離不開(kāi)線程操作,而我們需要在子線程中更新UI,一般有以下幾種方式:

  • 1、view.post(Runnable action)
  • 2、activity.runOnUiThread(Runnable action)
  • 3、AsyncTask
  • 4、Handler

而我們今天的主要目標(biāo)就是Handler,首先我們看下handler的官方定義:

  • Handler允許你通過(guò)使用一個(gè)與線程的MessageQueue相關(guān)聯(lián)的Message和Runnable對(duì)象去發(fā)送和處理消息。 每個(gè)處理程序?qū)嵗c單個(gè)線程和該線程的消息隊(duì)列相關(guān)聯(lián)。 當(dāng)您創(chuàng)建一個(gè)新的處理程序時(shí),它綁定到正在創(chuàng)建它的線程的線程/消息隊(duì)列 - 從那時(shí)起,它將向消息隊(duì)列傳遞消息和可運(yùn)行文件,并在消息發(fā)出時(shí)執(zhí)行它們 隊(duì)列。

  • Handler有兩個(gè)主要用途:(1)在可預(yù)見(jiàn)的時(shí)間內(nèi)去調(diào)度消息和作為一些點(diǎn)的可運(yùn)行程序(2)將不同于自己的線程執(zhí)行的操作排入隊(duì)列中。

  • 消息的調(diào)度是通過(guò)post(Runnable),postAtTime(Runnable,long),postDelayed(Runnable,long),sendEmptyMessage(int),sendMessage(Message),sendMessageAtTime(Message,long)和sendMessageDelayed(Message,long)來(lái)完成的 。 后臺(tái)版本允許你將接收到的消息隊(duì)列調(diào)用的Runnable對(duì)象排入隊(duì)列; sendMessage版本允許你將包含將由處理程序的handleMessage(Message)方法處理的數(shù)據(jù)包(要求您實(shí)現(xiàn)Handler的子類(lèi))的Message對(duì)象排入隊(duì)列。

  • 當(dāng)發(fā)布或發(fā)送到Handler時(shí),你可以在消息隊(duì)列準(zhǔn)備就緒后立即處理該項(xiàng)目或者指定一個(gè)延遲時(shí)間去處理該消息隊(duì)列,或者指定一個(gè)具體時(shí)間處理該消息。 后兩者允許您實(shí)現(xiàn)超時(shí),定時(shí)和其他基于時(shí)間的行為。
  • 當(dāng)為你的應(yīng)用創(chuàng)建一個(gè)進(jìn)程時(shí),其主線程專(zhuān)用于運(yùn)行一個(gè)消息隊(duì)列,該消息隊(duì)列負(fù)責(zé)管理頂級(jí)應(yīng)用程序?qū)ο螅╝ctivitys, broadcast receivers 等)及其創(chuàng)建的任何窗口。 你可以創(chuàng)建你自己的線程并通過(guò)Handler與主應(yīng)用程序線程進(jìn)行通信。 這可以通過(guò)從你的新線程中調(diào)用同樣的post或sendMessage方法來(lái)實(shí)現(xiàn)。 給定的Runnable或Message將在Handler的消息隊(duì)列中進(jìn)行調(diào)度,并在適當(dāng)時(shí)進(jìn)行處理。

    在查看Handler源碼之前,我們先了解幾個(gè)類(lèi):
    Handler 、Looper、MessageQueue、Message、ThreadLocation
    Handler我們就不在介紹該類(lèi),上面的官方文檔已給出了詳細(xì)的介紹,我們來(lái)看下其余幾個(gè):

  • 1、ThreadLocal:每個(gè)使用該變量的線程提供獨(dú)立的變量副本,每一個(gè)線程都可以獨(dú)立地改變自己的副本,而不會(huì)影響其它線程所對(duì)應(yīng)的副本。ThreadLocal內(nèi)部是通過(guò)map進(jìn)行實(shí)現(xiàn)的;
  • 2、Looper:可以理解為循環(huán)器,就是扶著管理一個(gè)消息循環(huán)隊(duì)列(MessageQueue)的;
  • 3、MessageQueue:消息隊(duì)列,用來(lái)存放handler發(fā)布的消息
  • 4、Message:消息體,封裝了我們傳輸消息所需的數(shù)據(jù)結(jié)構(gòu)。

那么我們從哪里開(kāi)始看起呢,好吧, 從創(chuàng)建一個(gè)Handler實(shí)例為入口,首先我們看handler的構(gòu)造方法:

```
public Handler() {
  this(null, false);
}
public Handler(Callback callback) {
  this(callback, false);
}
public Handler(Looper looper) {
    this(looper, null, false);
}
public Handler(Looper looper, Callback callback) {
    this(looper, callback, false);
}
public Handler(boolean async) {
  this(null, async);
}
public Handler(Callback callback, boolean async) {
  if (FIND_POTENTIAL_LEAKS) {
      final Class<? extends Handler> klass = getClass();
      if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
              (klass.getModifiers() & Modifier.STATIC) == 0) {
          Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
              klass.getCanonicalName());
      }
  }

  mLooper = Looper.myLooper();
  if (mLooper == null) {
      throw new RuntimeException(
          "Can't create handler inside thread that has not called Looper.prepare()");
  }
  mQueue = mLooper.mQueue;
  mCallback = callback;
  mAsynchronous = async;
}

public Handler(Looper looper, Callback callback, boolean async) {
  mLooper = looper;
  mQueue = looper.mQueue;
  mCallback = callback;
  mAsynchronous = async;
}

```
  • 可以看到,有多個(gè)構(gòu)造方法,但是最終都會(huì)調(diào)用到最后一個(gè)。我們看倒數(shù)第二個(gè),有這么一句: mLooper = Looper.myLooper();這里我們看到了個(gè)looper,可以看到,在handler里面會(huì)有一個(gè)mlooper對(duì)象與之關(guān)聯(lián),我們先不看mlooper是怎么來(lái)的,我們先把下面的看完;繼續(xù)看下面一句: mQueue = mLooper.mQueue;我們的handler里面也有一個(gè)隊(duì)列的對(duì)象,實(shí)際上mQueue就是MessageQueue,后面我們會(huì)講解到。好的,繼續(xù)往下看, mCallback = callback;一般情況下mCallback是null,我們通常new 一個(gè)Handler是不是調(diào)用的無(wú)參構(gòu)造方法?callback的作用后面也會(huì)講解到,好的最后一句: mAsynchronous = async;表示我們的執(zhí)行過(guò)程是異步的還是同步的,一般情況下,默認(rèn)是異步的。
小結(jié): Handler會(huì)存有Looper對(duì)象以及消息隊(duì)列mQueue,通過(guò)關(guān)聯(lián)looper與mQueue,可以想象,handler要把message插入消息隊(duì)列中,最直接的方式當(dāng)然是拿到消息隊(duì)列的實(shí)例,實(shí)現(xiàn)消息的發(fā)送;

  • 看了Handler的構(gòu)造,接下來(lái)我們看下Looper.mLooper:
    public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
    }
    -可以看到,Looper.myLooper內(nèi)部是調(diào)用了sThreadlocal.get();這個(gè)sThreadLocal其實(shí)就是我們之前說(shuō)的ThreadLocal類(lèi)的實(shí)例,他負(fù)責(zé)存儲(chǔ)當(dāng)先線程的Looper實(shí)例;是不是真的呢?我們看下sThreadLocal在哪里賦值的,很好,我們找到了一個(gè)prepare方法,看名字是準(zhǔn)備的意思,也就是為我們準(zhǔn)備我們需要的looper對(duì)象,我們繼續(xù)看:

     public static void prepare() {
      prepare(true);
    }
    
    private static void prepare(boolean quitAllowed) {
      if (sThreadLocal.get() != null) {
          throw new RuntimeException("Only one Looper may be created per thread");
      }
      sThreadLocal.set(new Looper(quitAllowed));
      }
    
    
  • 首先我們可以看到,會(huì)先判斷sThreadLocal.get() != null,說(shuō)明Looper.prepare()只能被調(diào)用一次哦,不然就會(huì)拋出異常,這樣做是為了保證一個(gè)線程只有一個(gè)looper存在,然后我們的可以看到里面通過(guò)new Looper(quitAllowed)獲得當(dāng)先線程的looper,我們繼續(xù)看Looper的構(gòu)造方法:

      private Looper(boolean quitAllowed) {
      mQueue = new MessageQueue(quitAllowed);
      mThread = Thread.currentThread();
        }
    
    
  • 在looper的構(gòu)造方法里,主要做了兩件事:1、創(chuàng)建一個(gè)looper管理的消息隊(duì)列 messageQueue;2、獲得當(dāng)前的線程;

小結(jié):Looper里面會(huì)存儲(chǔ)當(dāng)前的線程,以及所管理的消息隊(duì)列mQueue,一個(gè)Looper只會(huì)管理一個(gè)消息隊(duì)列MessageQueue;

  • 從上面的代碼中我們可以知道,在new 一個(gè)handler的同時(shí),我們就獲得了一個(gè)handler實(shí)例、一個(gè)當(dāng)前線程的looper、一個(gè)looper管理的messagequeue,好像擁有了這三個(gè)對(duì)象,我們就可以發(fā)送消息了哦。

  • 大家都知道looper從創(chuàng)建之后,就會(huì)開(kāi)始循環(huán),在looper類(lèi)的頂部,官方給出了一段代碼:

    class LooperThread extends Thread {
    public Handler mHandler;
    public void run() {
      Looper.prepare();
        mHandler = new Handler() {
           public void handleMessage(Message msg) {
              // process incoming messages here
           }
       };
        Looper.loop();
    }
    
    
  • 當(dāng)我們使用handler發(fā)消息時(shí),步驟是:

  • 1、 調(diào)用 Looper.prepare(); 初始化所需的looper以及messageQueue
  • 2、 實(shí)例化一個(gè)handler對(duì)象,我們可以在handleMessage獲得message做一些操作,此時(shí)handleMessage方法是在當(dāng)前的Looper中執(zhí)行的,也就是說(shuō),如果當(dāng)前的looper是UI Looper,那么你可以更新UI,如果當(dāng)前l(fā)ooper不是UI Looper,那么你更新UI肯定會(huì)報(bào)錯(cuò),你可能會(huì)說(shuō),我用handler時(shí),好像都不用調(diào)用Looper.prepare();,我怎么知道我當(dāng)前的looper是UI的還是不是呢,其實(shí)系統(tǒng)一般默認(rèn)都幫我們獲取了UI 的Looper,后面我們會(huì)講解到;
  • 3、調(diào)用 Looper.loop();讓Looper跑起來(lái)吧!

  • Looper.prepare();我們前面已經(jīng)分析過(guò)了,主要是實(shí)例化一個(gè)messageQueue,而且只能調(diào)用一次;那么我們重點(diǎn)就轉(zhuǎn)移懂到 Looper.loop();看源碼:

    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static void loop() {
      final Looper me = myLooper();
      if (me == null) {
          throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
      }
      final MessageQueue queue = me.mQueue;
    
      // Make sure the identity of this thread is that of the local process,
      // and keep track of what that identity token actually is.
      Binder.clearCallingIdentity();
      final long ident = Binder.clearCallingIdentity();
    
      for (;;) {
          Message msg = queue.next(); // might block
          if (msg == null) {
              // No message indicates that the message queue is quitting.
              return;
          }
    
          // This must be in a local variable, in case a UI event sets the logger
          final Printer logging = me.mLogging;
          if (logging != null) {
              logging.println(">>>>> Dispatching to " + msg.target + " " +
                      msg.callback + ": " + msg.what);
          }
    
          final long traceTag = me.mTraceTag;
          if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
              Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
          }
          try {
              msg.target.dispatchMessage(msg);
          } finally {
              if (traceTag != 0) {
                  Trace.traceEnd(traceTag);
              }
          }
    
          if (logging != null) {
              logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
          }
    
          // Make sure that during the course of dispatching the
          // identity of the thread wasn't corrupted.
          final long newIdent = Binder.clearCallingIdentity();
          if (ident != newIdent) {
              Log.wtf(TAG, "Thread identity changed from 0x"
                      + Long.toHexString(ident) + " to 0x"
                      + Long.toHexString(newIdent) + " while dispatching to "
                      + msg.target.getClass().getName() + " "
                      + msg.callback + " what=" + msg.what);
          }
    
          msg.recycleUnchecked();
      }
    }
    
    
  • 1、調(diào)用final Looper me = myLooper();獲得一個(gè)looper,myLooper方法我們前面分析過(guò),返回的是sThreadLocal中存儲(chǔ)的Looper實(shí)例,當(dāng)me==null拋出異常;所以,在looper執(zhí)行l(wèi)oop跑起來(lái)之前,我們要記得調(diào)用prepare()哦。當(dāng)獲得當(dāng)前的looper后,調(diào)用 final MessageQueue queue = me.mQueue; 獲取looper管理的MessageQueue;然后我們可以看到一個(gè)很有意思的for語(yǔ)句: for (;;) {...} 這就是循環(huán)的開(kāi)始了,此時(shí)我在想,我的天,這不是個(gè)無(wú)限死循話么?怎么可能呢?當(dāng)然有退出的條件,不然不就傻逼了么!

  • 2、我們可以看到:他會(huì)從looper的queue中獲取message,當(dāng)message==null,循環(huán)停止!
    Message msg = queue.next(); // might block
    if (msg == null) {
    // No message indicates that the message queue is quitting.
    return;
    }

  • 3、循環(huán)起來(lái)了,咱的looper也沒(méi)閑著,他一直知道它的工作是什么,我們可以看到:msg.target.dispatchMessage(msg);通過(guò)調(diào)用msg對(duì)象里的target對(duì)象的dispatchMessage(msg)方法把消息處理了。其實(shí)msg對(duì)象里的target對(duì)象就是我們new出來(lái)的handler,我們后面會(huì)講到。

小結(jié):

looper主要做了如下工作:

  • 1、將自己與當(dāng)前線程關(guān)聯(lián)在一起,通過(guò)ThreadLocal存儲(chǔ)當(dāng)前線程的looper,確保當(dāng)前線程只有一個(gè)looper實(shí)例;
  • 2、創(chuàng)建一個(gè)MessageQueue與當(dāng)前l(fā)ooper綁定,通過(guò)prepare方法控制looper只能有一個(gè)messageQueue實(shí)例;
  • 3、調(diào)用loop()方法,不斷從MessageQueue中去取消息,通過(guò)調(diào)用msg.target.dispatchMessage(msg)處理;

  • 分析完了looper、接下來(lái)當(dāng)然是hanlder發(fā)送消息了,我們又回到了handler中,我們通過(guò)handler發(fā)消息,自然少不了我們得sendMessag方法,那么我們就從它入手吧:

     public final boolean sendMessage(Message msg)
    {
      return sendMessageDelayed(msg, 0);
      }
    
     public final boolean sendEmptyMessage(int what)
    {
      return sendEmptyMessageDelayed(what, 0);
    }
    
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
      Message msg = Message.obtain();
      msg.what = what;
      return sendMessageDelayed(msg, delayMillis);
    }
    
    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
      Message msg = Message.obtain();
      msg.what = what;
      return sendMessageAtTime(msg, uptimeMillis);
    }
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
      if (delayMillis < 0) {
          delayMillis = 0;
      }
      return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
      MessageQueue queue = mQueue;
      if (queue == null) {
          RuntimeException e = new RuntimeException(
                  this + " sendMessageAtTime() called with no mQueue");
          Log.w("Looper", e.getMessage(), e);
          return false;
      }
      return enqueueMessage(queue, msg, uptimeMillis);
    }
    
    public final boolean sendMessageAtFrontOfQueue(Message msg) {
      MessageQueue queue = mQueue;
      if (queue == null) {
          RuntimeException e = new RuntimeException(
              this + " sendMessageAtTime() called with no mQueue");
          Log.w("Looper", e.getMessage(), e);
          return false;
      }
      return enqueueMessage(queue, msg, 0);
    }
    
    

  • 可以看到我們的sendMessage有多種方法,但最終都會(huì)調(diào)用enqueueMessage方法,我們看enqueueMessage方法源碼:
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
    msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
    }
  • 可以看到里面會(huì)講當(dāng)前的this賦值給msg.target,this
    當(dāng)前就是我們當(dāng)前的handler了,這也就是之前在分析looper時(shí)說(shuō)的,通過(guò)調(diào)用msg.target. dispatchMessage(msg)方法處理消息;后面后調(diào)用queue.enqueueMessage(msg, uptimeMillis);把消息放入當(dāng)前的looper的MessageQueue隊(duì)列中去處理,消息的發(fā)送流程就分析完了,發(fā)送了,接下來(lái)就是處理消息了!

  • 我們用handler時(shí),都是在handleMessage方法中處理消息的,那么我們就從handleMessage方法入手:
    /**

    • Subclasses must implement this to receive messages.
      */
      public void handleMessage(Message msg) {
      }
  • 可以看到handleMessage是一個(gè)空的方法,我們看handleMessage在哪被調(diào)用的呢?

      /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
      if (msg.callback != null) {
          handleCallback(msg);
      } else {
          if (mCallback != null) {
              if (mCallback.handleMessage(msg)) {
                  return;
              }
          }
          handleMessage(msg);
      }
    }
    
    
  • 可以看到handleMessage在dispatchMessage中被調(diào)用了,奇怪,怎么有兩個(gè)handleMessage方法呢?大家不要弄混了哦,我們handler的handleMessage方法返回值時(shí)void,所以mCallback.handleMessage肯定不是我們handler的了;

  • 第一個(gè)縣判斷msg.callback!=null 調(diào)用 handleCallback(msg);
    然后我們追進(jìn)去看:
    private static void handleCallback(Message message) {
    message.callback.run();
    }
    看到了run(),是不是想到了Runnable?其實(shí)message中的callback就是Runnable,我們可以從Message的創(chuàng)建函數(shù)中看到:
    private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
    }

  • 我們繼續(xù)回到dispatchMessage方法:也就是說(shuō),如果我們的給massge設(shè)置了callback,那么我們的handleMessage方法就不會(huì)被執(zhí)行了,當(dāng)然,一般我們的massge.callback都是null的。后面就會(huì)繼續(xù)判斷mCallback!=null如果成立則調(diào)用mCallback.handleMessage(msg) mCallback其實(shí)是一個(gè)回調(diào)接口,可以看到,如果mCallback.handleMessage(msg)返回true,就不會(huì)執(zhí)行我們的Handler.handleMessage方法,所以我們其實(shí)可以通過(guò)給handler添加Callback來(lái)實(shí)現(xiàn)一個(gè)message的過(guò)濾或者攔截功能。

  • 我們的Handler.handleMessage經(jīng)過(guò)重重阻撓,最終終于可以執(zhí)行了。

總結(jié):
  • 1、在Looper.prepare()中會(huì)通過(guò)sThreadLocal保存一個(gè)looper實(shí)例,控制當(dāng)前線程只能有一個(gè)looper實(shí)例;
  • 2、創(chuàng)建looper實(shí)例時(shí),會(huì)創(chuàng)建一個(gè)MessageQueue與looper關(guān)聯(lián);
  • 3、因?yàn)閘ooper只會(huì)存在一個(gè)實(shí)例,所以 當(dāng)前線程也會(huì)只存在一個(gè)MessageQueue隊(duì)列;
  • 4、調(diào)用Looper.loop()讓looper跑起來(lái)吧,然后looper就可以不停的從MessageQueue把消息拿出來(lái),然后通過(guò)調(diào)用msg.target.dispatchMessage(msg)處理消息,也是讓消息最終進(jìn)入我們的Handler.handleMessage方法,被我們給處理了;所以我們?cè)趯?shí)例化handler時(shí)需要重寫(xiě)handleMessage方法;
  • 5、實(shí)例化Handler時(shí),handler中會(huì)獲得當(dāng)前線程的looper以及l(fā)ooper的messageQueue;
  • 6、在調(diào)用sendMessage發(fā)送消息時(shí),最終會(huì)調(diào)用enqueueMessage方法,在enqueueMessage方法里會(huì)將msg.target=handler,講handler關(guān)聯(lián)到msg中,這樣looper在取出messageQueue中的消息時(shí),才知道該消息是要發(fā)給那個(gè)handler處理的,將handler與msg關(guān)聯(lián)后,就將msg加入隊(duì)列中去了,等待looper處理。

  • 使用Handler注意事項(xiàng):
  • 1、創(chuàng)建massage對(duì)象時(shí),推薦使用obtain()方法獲取,因?yàn)镸essage內(nèi)部會(huì)維護(hù)一個(gè)Message池用于Message的復(fù)用,這樣就可以避免 重新new message而沖內(nèi)心分配內(nèi)存,減少new 對(duì)象產(chǎn)生的資源的消耗。
  • 2、handler 的handleMessage方法內(nèi)部如果有調(diào)用外部activity或者fragment的對(duì)象,一定要用弱飲用,handler最好定義成static的,這樣可以避免內(nèi)存泄漏;為什么呢?因?yàn)橐坏玥andler發(fā)送了消息。而handler內(nèi)部有對(duì)外部變量的引用,此時(shí)handler已經(jīng)進(jìn)入了looper的messageQueue里面。此時(shí)activity或者fragment退出了可視區(qū)域,但是handler內(nèi)部持有其引用且為強(qiáng)引用時(shí),其就不會(huì)立即銷(xiāo)毀,產(chǎn)生延遲銷(xiāo)毀的情況。

面試問(wèn)題:
  • Handler延遲消息處理:
    MessageQueue,以隊(duì)列的形式管理message,message先進(jìn)先出,但其內(nèi)部是采用單鏈表來(lái)存儲(chǔ)消息列表。Handler的方法post(Runnable r)、postDelayed(Runnabler, long delayMillis)、sendMessage(Message msg)、sendMessageDelayed(Message msg, long delayMillis)最終調(diào)用的都是sendMessageAtTime(Message msg, long uptimeMillis),其中又調(diào)用了enqueueMessage()將msg插入隊(duì)列中。即不管發(fā)送的消息有沒(méi)有延遲,都會(huì)先插入隊(duì)列中,如果有延遲的話,looper不會(huì)立刻取出消息,時(shí)間到后才會(huì)取出消息,也就是延遲指延遲處理,不是延遲發(fā)送。
image

Handler可以調(diào)用sendMessageAtFrontOfQueue(Messagemsg),postAtFrontOfQueue(Runnable r),將消息插入隊(duì)頭,最先取出,最先執(zhí)行,之后再處理隊(duì)列中的其他消息。

image

如果隊(duì)列中只有延遲消息,此時(shí)發(fā)送一個(gè)普通消息,普通消息會(huì)插入隊(duì)頭,最先處理,而不會(huì)等延遲消息取出后,再取出普通消息。

  • 為什么在ActivityThread的main方法中有死循環(huán)(Loop.loop()),不會(huì)卡死

我們看到在ActivityThread的main中調(diào)用了 Looper.loop()

    public static void main(String[] args) {
    ......
    Looper.prepareMainLooper();

    //建立一個(gè)Binder通道(會(huì)創(chuàng)建新線程,向主線程的messageQueue中發(fā)送消息)
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    ......
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

要說(shuō)清楚問(wèn)題,我們要知道android是基于消息驅(qū)動(dòng)的。具體體現(xiàn)在上述代碼中,在代碼注釋的地方我們可以看到 ActivityThread thread = new ActivityThread(); thread.attach(false);這兩行代碼,執(zhí)行這兩句代碼會(huì)建立一個(gè)與ActivityManagerService連接的binder通道。ActivityManagerService負(fù)責(zé)管理所有activity的生命周期方法,例如oncreat,onresume等,當(dāng)ActivityManagerService開(kāi)始需要activity執(zhí)行生命周期方法時(shí),會(huì)首先通過(guò)建立好的binder通道調(diào)用應(yīng)用程序進(jìn)程的ApplicationThread的相關(guān)方法中。ApplicationThread會(huì)通過(guò)一個(gè)類(lèi)型為Handler的H類(lèi)將相關(guān)信息發(fā)送到主線程的消息隊(duì)列中,然后通過(guò)handler來(lái)處理這個(gè)消息。這樣就不會(huì)導(dǎo)致程序的主線程卡死。
上面只是說(shuō)明了一種情況(activity的生命周期調(diào)用),其實(shí)所有的情況都是如此。又比如界面的更新:當(dāng)界面需要更新的時(shí)候,也是講這個(gè)消息封裝在message對(duì)象中,然后添加到主線程的消息隊(duì)列中,由消息隊(duì)列統(tǒng)一管理。因此有消息時(shí)會(huì)進(jìn)行處理,沒(méi)有消息時(shí),主線程處于休眠狀態(tài)。
所以,由于android主線程是基于消息驅(qū)動(dòng)的,因此雖然有Loop.loop()這個(gè)死循環(huán),但是主線程不會(huì)卡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容