我們?cè)趎ew Handler()時(shí)候,實(shí)際上調(diào)用的是兩個(gè)參數(shù)的構(gòu)造方法,我們看下
public Handler() { this(null, false); }
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 null mCallback = callback; // mAsynchronous false mAsynchronous = async; }
我們看下myLooper()方法,
public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
sThreadLocal是什么我們看下:
// sThreadLocal.get() will return null unless you"ve called prepare(). static final ThreadLocalsThreadLocal = new ThreadLocal ();
在沒(méi)有調(diào)用Looper的prepare()情況下回返回null,我們看下prepare()方法的實(shí)現(xiàn):
private static void prepare(boolean quitAllowed) { //一個(gè)Thread只能有一個(gè)Looper綁定 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
現(xiàn)在終于可以看下Looper是構(gòu)造方法了
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
到這里Handler的mLooper和mQueue就找到出處了
我們看下sendMessage()做了什么:
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } //uptimeMillis() 從開(kāi)機(jī)到現(xiàn)在的毫秒數(shù) return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { //looper中創(chuàng)建的queue MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } // 加入隊(duì)列 return enqueueMessage(queue, msg, uptimeMillis); }
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { // 在這里我們注意下我們給msg添加了一個(gè)target是handler對(duì)象 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
這里調(diào)用了MessageQueue的enqueueMessae()方法,把我們的msg添加到queue里
我們?cè)賮?lái)看下Looper.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 { //================================================================== // 重點(diǎn)代碼在這里 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(); } }
重點(diǎn)代碼是 msg.target.dispatchMessage(msg);這句代碼,msg的target對(duì)象實(shí)際就是Handler,我們看下Handler的dispatchMessage()方法。
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
看到了我們熟悉的handleMessaee()方法
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70227.html
摘要:機(jī)制處理的個(gè)關(guān)鍵對(duì)象線程之間傳遞的消息,可以攜帶一些簡(jiǎn)單的數(shù)據(jù)供子線程與主線程進(jìn)行交換數(shù)據(jù)。解決方法子線程通過(guò)發(fā)送消息給主線程,讓主線程處理消息,進(jìn)而更新。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 極力推薦文章:歡迎收藏Android 干貨分享 showImg(https://...
摘要:在級(jí)事件中定義了個(gè)鼠標(biāo)事件,分別是。取消鼠標(biāo)事件的默認(rèn)行為還會(huì)影響其他事件,因?yàn)槭髽?biāo)事件與其他事件是密不可分的關(guān)系。同樣的,和支持這個(gè)事件。兼容各個(gè)瀏覽器的事件監(jiān)聽(tīng)對(duì)象該對(duì)象封裝了和級(jí)事件的常用事件函數(shù)。 概述 鼠標(biāo)事件是web開(kāi)發(fā)中最常用的一類(lèi)事件,畢竟鼠標(biāo)還是最主要的定位設(shè)備。在DOM3級(jí)事件中定義了9個(gè)鼠標(biāo)事件,分別是:click,dbclick,mousedown,mousee...
摘要:使用級(jí)方法指定的事件處理程序被認(rèn)為是元素的方法。用于立即停止事件在中的傳播,取消進(jìn)一步的事件捕獲或冒泡。捕獲事件目標(biāo)對(duì)象冒泡只有在事件處理程序執(zhí)行期間,對(duì)象才會(huì)存在,執(zhí)行完成后,對(duì)象就會(huì)被銷(xiāo)毀。 引用 事件是我認(rèn)為前端最特別的地方,這是唯一其他語(yǔ)言不一樣的地方,我們通過(guò)它與頁(yè)面進(jìn)行交互。 事件流 事件流描述的是從頁(yè)面中接收事件的順序。IE和網(wǎng)景團(tuán)隊(duì)提出流相反的事件流概念。IE事件流是事...
閱讀 3711·2023-04-25 22:43
閱讀 3706·2021-09-06 15:15
閱讀 1332·2019-08-30 15:54
閱讀 3543·2019-08-30 14:20
閱讀 2884·2019-08-29 17:16
閱讀 3117·2019-08-29 15:28
閱讀 3397·2019-08-29 11:08
閱讀 1071·2019-08-28 18:05