日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析

發布時間:2025/3/15 Android 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1、Handler的由來

  當程序第一次啟動的時候,Android會同時啟動一條主線程( Main Thread)來負責處理與UI相關的事件,我們叫做UI線程。

  Android的UI操作并不是線程安全的(出于性能優化考慮),意味著如果多個線程并發操作UI線程,可能導致線程安全問題。

  為了解決Android應用多線程問題—Android平臺只允許UI線程修改Activity里的UI組建,就會導致新啟動的線程無法改變界面組建的屬性值。

  簡單的說:當主線程隊列處理一個消息超過5秒,android 就會拋出一個 ANR(無響應)的異常,所以,我們需要把一些要處理比較長的消息,放在一個單獨線程里面處理,把處理以后的結果,返回給主線程運行,就需要用的Handler來進行線程建的通信。

2、Handler的作用

2.1 讓線程延時執行

主要用到的兩個方法:

  • final boolean postAtTime(Runnable r, long uptimeMillis)

  • final boolean postDelayed(Runnable r, long delayMillis)

2.2 讓任務在其他線程中執行并返回結果

分為兩個步驟:

  • 在新啟動的線程中發送消息

      使用Handler對象的sendMessage()方法或者SendEmptyMessage()方法發送消息。

  • 在主線程中獲取處理消息

      重寫Handler類中處理消息的方法(void handleMessage(Message msg)),當新啟動的線程發送消息時,消息發送到與之關聯的MessageQueue。而Hanlder不斷地從MessageQueue中獲取并處理消息。

3、Handler更新UI線程一般使用

  • 首先要進行Handler 申明,復寫handleMessage方法( 放在主線程中)
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> Handler handler = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Handler() {<span class="hljs-annotation" style="color:#9b859d;box-sizing: border-box;">@Override</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">handleMessage</span>(Message msg) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// TODO 接收消息并且去更新UI線程上的控件內容</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (msg.what == UPDATE) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 更新界面上的textview</span>tv.setText(String.valueOf(msg.obj));}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">super</span>.handleMessage(msg);}};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>
  • 子線程發送Message給ui線程表示自己任務已經執行完成,主線程可以做相應的操作了。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Thread() {<span class="hljs-annotation" style="color:#9b859d;box-sizing: border-box;">@Override</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>() {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// TODO 子線程中通過handler發送消息給handler接收,由handler去更新TextView的值</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//do something</span>Message msg = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Message();msg.what = UPDATE; msg.obj = <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"更新后的值"</span> ;handler.sendMessage(msg);}} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (InterruptedException e) {e.printStackTrace();}}}.start();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>
4、Handler原理分析

4.1  Handler的構造函數

① public Handler()?
② public Handler(Callbackcallback)?
③ public Handler(Looperlooper)?
④ public Handler(Looperlooper, Callbackcallback)  

  • 第①個和第②個構造函數都沒有傳遞Looper,這兩個構造函數都將通過調用Looper.myLooper()獲取當前線程綁定的Looper對象,然后將該Looper對象保存到名為mLooper的成員字段中。  ?
      下面來看①②個函數源碼:?
      
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color:#06666;box-sizing: border-box;">113</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Handler</span>() { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">114</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">115</span> }<span class="hljs-number" style="color:#06666;box-sizing: border-box;">127</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Handler</span>(Callback callback) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">128</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>(callback, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">129</span> }<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//他們會調用Handler的內部構造方法</span><span class="hljs-number" style="color:#06666;box-sizing: border-box;">188</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Handler</span>(Callback callback, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> async) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">189</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (FIND_POTENTIAL_LEAKS) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">190</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> Class<? extends Handler> klass = getClass(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">191</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> ((klass.isAnonymousClass() ||klass.isMemberClass()|| klass.isLocalClass()) && <span class="hljs-number" style="color:#06666;box-sizing: border-box;">192</span> (klass.getModifiers() & Modifier.STATIC) == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">193</span> Log.w(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"The following Handler class should be static or leaks might occur: "</span> + <span class="hljs-number" style="color:#06666;box-sizing: border-box;">194</span> klass.getCanonicalName()); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">195</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">196</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">197</span><span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/************************************ 198 mLooper = Looper.myLooper(); 199 if (mLooper == null) { 200 throw new RuntimeException( 201 "Can't create handler inside thread that has not called Looper.prepare()"); 202 } 203 mQueue = mLooper.mQueue; 204 mCallback = callback; 205 mAsynchronous = async; 206 } </span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul>

  我們看到暗紅色的重點部分:

  通過Looper.myLooper()獲取了當前線程保存的Looper實例,又通過這個Looper實例獲取了其中保存的MessageQueue(消息隊列)。每個Handler 對應一個Looper對象,產生一個MessageQueue?
  

  • 第③個和第④個構造函數傳遞了Looper對象,這兩個構造函數會將該Looper保存到名為mLooper的成員字段中。?
      下面來看③④個函數源碼:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color:#06666;box-sizing: border-box;">136</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Handler</span>(Looper looper) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">137</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>(looper, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">138</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">147</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Handler</span>(Looper looper, Callback callback) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">148</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>(looper, callback, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">149</span> } <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//他們會調用Handler的內部構造方法</span><span class="hljs-number" style="color:#06666;box-sizing: border-box;">227</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Handler</span>(Looper looper, Callback callback, boolean <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">async</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">228</span> mLooper = looper; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">229</span> mQueue = looper.mQueue; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">230</span> mCallback = callback; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">231</span> mAsynchronous = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">async</span>; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">232</span> } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
  • 第②個和第④個構造函數還傳遞了Callback對象,Callback是Handler中的內部接口,需要實現其內部的handleMessage方法,Callback代碼如下:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color:#06666;box-sizing: border-box;">80</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">interface</span> Callback { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">81</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> boolean More ...<span class="hljs-title" style="box-sizing: border-box;">handleMessage</span>(Message msg); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">82</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

  Handler.Callback是用來處理Message的一種手段,如果沒有傳遞該參數,那么就應該重寫Handler的handleMessage方法,也就是說為了使得Handler能夠處理Message,我們有兩種辦法:?
  ?
 1. 向Hanlder的構造函數傳入一個Handler.Callback對象,并實現Handler.Callback的handleMessage方法  ?
  ?
 2. 無需向Hanlder的構造函數傳入Handler.Callback對象,但是需要重寫Handler本身的handleMessage方法  ?
   ?
   也就是說無論哪種方式,我們都得通過某種方式實現handleMessage方法,這點與Java中對Thread的設計有異曲同工之處。

4.2 Handle發送消息的幾個方法源碼

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">sendMessage</span>(Message msg){<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> sendMessageDelayed(msg, <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul> <code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">sendEmptyMessageDelayed</span>(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> what, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">long</span> delayMillis) {Message msg = Message.obtain();msg.what = what;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> sendMessageDelayed(msg, delayMillis);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul> <code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">sendMessageDelayed</span>(Message msg, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">long</span> delayMillis){<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (delayMillis < <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>) {delayMillis = <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>;}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul> <code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">sendMessageAtTime</span>(Message msg, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">long</span> uptimeMillis) {MessageQueue queue = mQueue;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (queue == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {RuntimeException e = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> RuntimeException(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span> + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" sendMessageAtTime() called with no mQueue"</span>);Log.w(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Looper"</span>, e.getMessage(), e);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> enqueueMessage(queue, msg, uptimeMillis);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

我們可以看出他們最后都調用了sendMessageAtTime(),然后返回了enqueueMessage方法,下面看一下此方法源碼:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color:#06666;box-sizing: border-box;">626</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">enqueueMessage</span>(MessageQueue queue, Message msg, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">long</span> uptimeMillis) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把當前的handler作為msg的target屬性</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">627</span> msg.target = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">628</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (mAsynchronous) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">629</span> msg.setAsynchronous(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">630</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">631</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> queue.enqueueMessage(msg, uptimeMillis); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">632</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

在該方法中有兩件事需要注意:

  • msg.target = this

      該代碼將Message的target綁定為當前的Handler

  • queue.enqueueMessage?
      ?
      變量queue表示的是Handler所綁定的消息隊列MessageQueue,通過調用queue.enqueueMessage(msg, uptimeMillis)我們將Message放入到消息隊列中。
  • 過下圖可以看到完整的方法調用順序:

     

    5、Looper原理分析

      我們一般在主線程申明Handler,有時我們需要繼承Thread類實現自己的線程功能,當我們在里面申明Handler的時候會報錯。其原因是主線程中已經實現了兩個重要的Looper方法,下面看一看ActivityThread.java中main方法的源碼:

    <code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//......省略</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5205</span> Looper.prepareMainLooper();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//></span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5206</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5207</span> ActivityThread thread = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> ActivityThread(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5208</span> thread.attach(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5209</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5210</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (sMainThreadHandler == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5211</span> sMainThreadHandler = thread.getHandler(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5212</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5213</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5214</span> AsyncTask.init(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5215</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5216</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5217</span> Looper.myLooper().setMessageLogging(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5218</span> LogPrinter(Log.DEBUG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"ActivityThread"</span>)); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5219</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5220</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5221</span> Looper.loop();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//></span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5222</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5223</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> RuntimeException(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Main thread loop unexpectedly exited"</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5224</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">5225</span>}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

    5.1 首先看prepare()方法

    <code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color:#06666;box-sizing: border-box;">70</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">prepare</span>() { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">71</span> prepare(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">72</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">73</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">74</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">prepare</span>(boolean quitAllowed) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//證了一個線程中只有一個Looper實例</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">75</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (sThreadLocal.<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">get</span>() != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">76</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> RuntimeException(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Only one Looper may be created per thread"</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">77</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">78</span> sThreadLocal.<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">set</span>(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Looper(quitAllowed)); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">79</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

    該方法會調用Looper構造函數同時實例化出MessageQueue和當前thread.

    <code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color:#06666;box-sizing: border-box;">186</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-title" style="box-sizing: border-box;">Looper</span>(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> quitAllowed) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">187</span> mQueue = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> MessageQueue(quitAllowed); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">188</span> mThread = Thread.currentThread(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">189</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">182</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> MessageQueue <span class="hljs-title" style="box-sizing: border-box;">myQueue</span>() { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">183</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> myLooper().mQueue; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">184</span> } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

      prepare()方法中通過ThreadLocal對象實現Looper實例與線程的綁定。 

    5.2  loop()方法

    <code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color:#06666;box-sizing: border-box;">109</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">loop</span>() { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">110</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> Looper me = myLooper(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">111</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (me == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">112</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> RuntimeException(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"No Looper; Looper.prepare() wasn't called on this thread."</span>); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">113</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">114</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> MessageQueue queue = me.mQueue; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">115</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">118</span> Binder.clearCallingIdentity(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">119</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">long</span> ident = Binder.clearCallingIdentity(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">120</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">121</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> (;;) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">122</span> Message msg = queue.next(); <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// might block</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">123</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (msg == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">124</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">125</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">126</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">127</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">129</span> Printer logging = me.mLogging; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">130</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (logging != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">131</span> logging.println(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">">>>>> Dispatching to "</span> + msg.target + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" "</span> + <span class="hljs-number" style="color:#06666;box-sizing: border-box;">132</span> msg.callback + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">": "</span> + msg.what); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">133</span> } <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//重點****</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">135</span> msg.target.dispatchMessage(msg); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">136</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">137</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (logging != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">138</span> logging.println(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"<<<<< Finished to "</span> + msg.target + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" "</span> + msg.callback); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">139</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">140</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">142</span> <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// identity of the thread wasn't corrupted.</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">143</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">long</span> newIdent = Binder.clearCallingIdentity(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">144</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (ident != newIdent) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">145</span> Log.wtf(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Thread identity changed from 0x"</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">146</span> + Long.toHexString(ident) + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" to 0x"</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">147</span> + Long.toHexString(newIdent) + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" while dispatching to "</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">148</span> + msg.target.getClass().getName() + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" "</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">149</span> + msg.callback + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" what="</span> + msg.what); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">150</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">151</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">152</span> msg.recycleUnchecked(); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">153</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">154</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li></ul>

      首先looper對象不能為空,就是說loop()方法調用必須在prepare()方法的后面。

     Looper一直在不斷的從消息隊列中通過MessageQueue的next方法獲取Message,然后通過代碼msg.target.dispatchMessage(msg)讓該msg所綁定的Handler(Message.target)執行dispatchMessage方法以實現對Message的處理。

    Handler的dispatchMessage的源碼如下:

    <code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color:#06666;box-sizing: border-box;">93</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">dispatchMessage</span>(Message msg) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">94</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (msg.callback != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">95</span> handleCallback(msg); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">96</span> } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">97</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (mCallback != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">98</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (mCallback.handleMessage(msg)) { <span class="hljs-number" style="color:#06666;box-sizing: border-box;">99</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>; <span class="hljs-number" style="color:#06666;box-sizing: border-box;">100</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">101</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">102</span> handleMessage(msg); <span class="hljs-number" style="color:#06666;box-sizing: border-box;">103</span> } <span class="hljs-number" style="color:#06666;box-sizing: border-box;">104</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>

      我們可以看到Handler提供了三種途徑處理Message,而且處理有前后優先級之分:首先嘗試讓postXXX中傳遞的Runnable執行,其次嘗試讓Handler構造函數中傳入的Callback的handleMessage方法處理,最后才是讓Handler自身的handleMessage方法處理Message。

    6、如何在子線程中使用Handler

      Handler本質是從當前的線程中獲取到Looper來監聽和操作MessageQueue,當其他線程執行完成后回調當前線程。

      子線程需要先prepare()才能獲取到Looper的,是因為在子線程只是一個普通的線程,其ThreadLoacl中沒有設置過Looper,所以會拋出異常,而在Looper的prepare()方法中sThreadLocal.set(new Looper())是設置了Looper的。

    6.1 實例代碼

     定義一個類實現Runnable接口或繼承Thread類(一般不繼承)。

    <code class="hljs axapta has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">class</span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">Rub</span> <span class="hljs-inheritance" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">implements</span></span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">Runnable</span> {</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> Handler myHandler; <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 實現Runnable接口的線程體 </span>@Override <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> run() { <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">/*①、調用Looper的prepare()方法為當前線程創建Looper對象并,創建Looper對象時,它的構造器會自動的創建相對應的MessageQueue*/</span>Looper.prepare(); <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">/*.②、創建Handler子類的實例,重寫HandleMessage()方法,該方法處理除當前線程以外線程的消息*/</span>myHandler = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Handler() { @Override <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> handleMessage(Message msg) { String ms = <span class="hljs-string" style="color:#0880;box-sizing: border-box;">""</span>; <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (msg.what == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0x777</span>) { } } }; <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//③、調用Looper的loop()方法來啟動Looper讓消息隊列轉動起來</span>Looper.loop(); }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

    注意分成三步: 

    1.調用Looper的prepare()方法為當前線程創建Looper對象,創建Looper對象時,它的構造器會創建與之配套的MessageQueue。  

    2.有了Looper之后,創建Handler子類實例,重寫HanderMessage()方法,該方法負責處理來自于其他線程的消息。  

    3.調用Looper的looper()方法啟動Looper。

      然后使用這個handler實例在任何其他線程中發送消息,最終處理消息的代碼都會在你創建Handler實例的線程中運行。

    7、總結

    Handler:?
          發送消息,它能把消息發送給Looper管理的MessageQueue。?
          處理消息,并負責處理Looper分給它的消息。?
    Message:?
          Handler接收和處理的消息對象。?
    Looper:?
          每個線程只有一個Looper,它負責管理對應的MessageQueue,會不斷地從MessageQueue取出消息,并將消息分給對應的Hanlder處理。  ?
          ?
          主線程中,系統已經初始化了一個Looper對象,因此可以直接創建Handler即可,就可以通過Handler來發送消息、處理消息。 程序自己啟動的子線程,程序必須自己創建一個Looper對象,并啟動它,調用Looper.prepare()方法。

    prapare()方法:保證每個線程最多只有一個Looper對象。  

    looper()方法:啟動Looper,使用一個死循環不斷取出MessageQueue中的消息,并將取出的消息分給對應的Handler進行處理。  

    MessageQueue:由Looper負責管理,它采用先進先出的方式來管理Message。 

      Handler的構造方法,會首先得到當前線程中保存的Looper實例,進而與Looper實例中的MessageQueue想關聯。 ?
      ?
      Handler的sendMessage方法,會給msg的target賦值為handler自身,然后加入MessageQueue中。



    原文地址: http://blog.csdn.net/amazing7/article/details/51424038

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。