Android中handler的工作原理

来源:互联网 发布:python ggplot2 编辑:程序博客网 时间:2024/05/23 19:42

通过源码我们知道一个线程中只有一个looper对象,同时looper对象生成了一个Messagequeue对象,当我们new一个handler对象时,其实我们是吧上面生成的两个对象给取了出来保存在handler内部定义的变量里面,调用handler的sendmessage()时连同handler对象一起发送到messagequeue队列中去。looper.loop()负责将消息队列中的消息取出来

public static void loop() {          ……          final MessageQueue queue = me.mQueue;          for (;;) {              Message msg = queue.next(); // might block              if (msg == null) {                  return;              }              ……              msg.target.dispatchMessage(msg);              ……              msg.recycle();          }  } 
<span style="font-size:18px;">target是handler对象,就是我们生成的,然后调用</span><pre name="code" class="java" style="font-size:18px;"><span style="background-color: rgb(204, 204, 204);">dispatchMessage(msg)方法,</span>
<pre style="color: rgb(169, 183, 198); font-family: Consolas; font-size: 15pt;"><span style="background-color: rgb(204, 204, 204);"><span style="color: rgb(204, 120, 50);"></span></span><pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'Consolas';font-size:15.0pt;"><span style="color:#cc7832;">public void </span><span style="color:#ffc66d;">dispatchMessage</span>(Message msg) {    <span style="color:#cc7832;">if </span>(msg.callback != <span style="color:#cc7832;">null</span>) {        <span style="font-style:italic;">handleCallback</span>(msg)<span style="color:#cc7832;">;</span><span style="color:#cc7832;">    </span>} <span style="color:#cc7832;">else </span>{        <span style="color:#cc7832;">if </span>(<span style="color:#9876aa;">mCallback </span>!= <span style="color:#cc7832;">null</span>) {            <span style="color:#cc7832;">if </span>(<span style="color:#9876aa;">mCallback</span>.handleMessage(msg)) {                <span style="color:#cc7832;">return;</span><span style="color:#cc7832;">            </span>}        }        handleMessage(msg)<span style="color:#cc7832;">;</span><span style="color:#cc7832;">    </span>}}

这里面就有我们要的handleMessage,即我们重写的方法。
message获得的方法<pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'Consolas';font-size:15.0pt;"><span style="color:#cc7832;">public final </span>Message <span style="color:#ffc66d;">obtainMessage</span>(){    <span style="color:#cc7832;">return </span>Message.<span style="font-style:italic;">obtain</span>(<span style="color:#cc7832;">this</span>)<span style="color:#cc7832;">;</span>}
将handler对象传了进去,那么我们 看看message这个方法
public static Message obtain(Handler h) {    Message m = obtain();    m.target = h;    return m;}

将消息和handler一起保存了下来,一起发送到消息队列中去了
因此我们可以总结一下handler的工作机制是这样的
一个线程对应一个looper,一个looper对应一个MessageQueue,当我们new了一个handler时,我们将这个线程中的looper和<pre name="code" class="java" style="font-size:18px;">MessageQueue取了出来放在handler对象中的成员变量中,也就是说不管我们new 了多少个handler我们在一个线程中只有一个looper和MessageQueue,同时我们在哪个线程中new,handler就与哪个线程想关联
handler的创建过过程
<pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'Consolas';font-size:15.0pt;"><span style="color:#cc7832;">public </span>Handler() {    <span style="color:#cc7832;">this</span>(<span style="color:#cc7832;">null, false</span>)<span style="color:#cc7832;">;</span>}

<pre style="font-family: Consolas; color: rgb(169, 183, 198); background-color: rgb(43, 43, 43);"><span style="font-size: 15pt;"> </span><span style="font-size: 15pt; color: rgb(98, 151, 85); "><em>*/</em></span><span style="font-size: 15pt; color: rgb(204, 120, 50);">public </span><span style="font-size: 15pt;">Handler(Callback callback</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">, boolean </span><span style="font-size: 15pt;">async) {    </span><span style="font-size: 15pt; color: rgb(204, 120, 50);">if </span><span style="font-size: 15pt;">(</span><span style="font-size: 15pt; color: rgb(152, 118, 170); "><em>FIND_POTENTIAL_LEAKS</em></span><span style="font-size: 15pt;">) {        </span><span style="font-size: 15pt; color: rgb(204, 120, 50);">final </span><span style="font-size: 15pt;">Class<? </span><span style="font-size: 15pt; color: rgb(204, 120, 50);">extends </span><span style="font-size: 15pt;">Handler> klass = getClass()</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">;</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">        if </span><span style="font-size: 15pt;">((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                (klass.getModifiers() & Modifier.</span><span style="font-size: 15pt; color: rgb(152, 118, 170); "><em>STATIC</em></span><span style="font-size: 15pt;">) == </span><span style="font-size: 15pt; color: rgb(104, 151, 187);">0</span><span style="font-size: 15pt;">) {            Log.</span><span style="font-size: 15pt; font-style: italic;">w</span><span style="font-size: 15pt;">(</span><span style="font-size: 15pt; color: rgb(152, 118, 170); "><em>TAG</em></span><span style="font-size: 15pt; color: rgb(204, 120, 50);">, </span><span style="font-size: 15pt; color: rgb(106, 135, 89);">"The following Handler class should be static or leaks might occur: " </span><span style="font-size: 15pt;">+                klass.getCanonicalName())</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">;</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">        </span><span style="font-size: 15pt;">}    }    </span><span style="font-size: 15pt; color: rgb(152, 118, 170);">mLooper </span><span style="font-size: 15pt;">= Looper.</span><span style="font-size: 15pt; font-style: italic;">myLooper</span><span style="font-size: 15pt;">()</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">;</span><span style="color: rgb(204, 120, 50);"><span style="font-size: 15pt;">  </span><span style="font-size:32px;">  if </span></span><span style="font-size:32px;">(<span style="color: rgb(152, 118, 170);">mLooper </span>== <span style="color: rgb(204, 120, 50);">null</span>) {        <span style="color: rgb(204, 120, 50);">throw new </span>RuntimeException(            <span style="color: rgb(106, 135, 89);">"Can't create handler inside thread that has not called Looper.prepare()"</span>)<span style="color: rgb(204, 120, 50);">;</span><span style="color: rgb(204, 120, 50);">    </span>}</span><span style="font-size: 15pt;">    </span><span style="font-size: 15pt; color: rgb(152, 118, 170);">mQueue </span><span style="font-size: 15pt;">= </span><span style="font-size: 15pt; color: rgb(152, 118, 170);">mLooper</span><span style="font-size: 15pt;">.</span><span style="font-size: 15pt; color: rgb(152, 118, 170);">mQueue</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">;</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">    </span><span style="font-size: 15pt; color: rgb(152, 118, 170);">mCallback </span><span style="font-size: 15pt;">= callback</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">;</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">    </span><span style="font-size: 15pt; color: rgb(152, 118, 170);">mAsynchronous </span><span style="font-size: 15pt;">= async</span><span style="font-size: 15pt; color: rgb(204, 120, 50);">;</span><span style="font-size: 15pt;">}</span>
看我们放大的部分,如果mLooper为空的话就出错。
具体的可以看mars视频的重置第二集。


0 0
原创粉丝点击