<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                #### 10.2.3 Looper的工作原理 在10.2.2節中介紹了消息隊列的主要實現,本節將分析[Looper](https://www.androidos.net.cn/android/6.0.1_r16/xref/frameworks/base/core/java/android/os/Looper.java)的具體實現。**Looper在Android的消息機制中扮演著消息循環的角色**,具體來說就是**它會不停地從MessageQueue中查看是否有新消息,如果有新消息就會立刻處理,否則就一直阻塞在那里**。首先看一下它的構造方法,在構造方法中它會創建一個MessageQueue即消息隊列,然后將當前線程的對象保存起來,如下所示。 ``` private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } ``` 我們知道,**Handler的工作需要Looper,沒有Looper的線程就會報錯,那么如何為一個線程創建Looper呢**? 其實很簡單,**通過Looper.prepare()即可為當前線程創建一個Looper,接著通過Looper.loop()來開啟消息循環**,如下所示。 ``` new Thread("Thread#2") { @Override public void run() { Looper.prepare(); Handler handler = new Handler(); Looper.loop(); }; }.start(); ``` Looper除了prepare方法外,還提供了**prepareMainLooper**方法,這個方法**主要是給主線程(UI線程)也就是ActivityThread所在的線程創建Looper使用的,其本質也是通過prepare方法來實現的**。由于主線程的Looper比較特殊,所以**Looper提供了一個getMainLooper方法,通過它可以在任何地方獲取到主線程的Looper**。 **Looper也是可以退出的**,Looper提供了**quit和quitSafely**來退出一個Looper,二者的區別是:**quit會直接退出Looper,而quitSafely只是設定一個退出標記,然后把消息隊列中的已有消息處理完畢后才安全地退出**。 Looper退出后,通過Handler發送的消息會失敗,這個時候Handler的send方法會返回false。**在子線程中,如果手動為其創建了Looper,那么在所有的事情完成以后應該調用quit方法來終止消息循環,否則這個子線程就會一直處于等待的狀態,而如果退出Looper以后,這個線程就會立刻終止,因此建議不需要的時候終止Looper**。 **Looper最重要的一個方法是loop方法,只有調用了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();//獲取TLS存儲的Looper對象 if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue;//獲取Looper對象中的消息隊列 Binder.clearCallingIdentity(); //確保在權限檢查時基于本地進程,而不是調用進程。 final long ident = Binder.clearCallingIdentity(); for (;;) {//進入loop的主循環方法 Message msg = queue.next(); //可能會阻塞 if (msg == null) { //沒有消息,則退出循環 return; } //默認為null,可通過setMessageLogging()方法來指定輸出,用于debug功能 Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg);//用于分發Message if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } //恢復調用者信息 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();//將Message放入消息池 } } ``` Looper的loop方法的工作過程也比較好理解,**loop方法是一個死循環,唯一跳出循環的方式是MessageQueue的next方法返回了null。當Looper的quit方法被調用時,Looper就會調用MessageQueue的quit或者quitSafely方法來通知消息隊列退出,當消息隊列被標記為退出狀態時,它的next方法就會返回null**。也就是說,**Looper必須退出,否則loop方法就會無限循環下去**。 loop方法會調用MessageQueue的next方法來獲取新消息,而**next是一個阻塞操作,當沒有消息時,next方法會一直阻塞在那里,這也導致loop方法一直阻塞在那里**。**如果MessageQueue的next方法返回了新消息,Looper就會處理這條消息:`msg.target.dispatchMessage(msg)`,**這里的**msg.target是發送這條消息的Handler對象,這樣Handler發送的消息最終又交給它的dispatchMessage方法來處理了。但是這里不同的是,Handler的dispatchMessage方法是在創建Handler時所使用的Looper中執行的,這樣就成功地將代碼邏輯切換到指定的線程中去執行了**。 **在Looper的構造方法中會去保存當前的線程,Looper在哪個線程創建,Handler的dispatchMessage方法終究會在那個線程執行**。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看