日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > 綜合技術(shù) > Android消息機(jī)制

Android消息機(jī)制

來源:程序員人生   發(fā)布時(shí)間:2016-11-29 09:00:38 閱讀次數(shù):2539次

最近決定把之前學(xué)習(xí)過的東西整理1遍,然后把寫得1些代碼review1遍,今天來學(xué)習(xí)1下消息機(jī)制,之前學(xué)過,沒太弄清楚,有很多都忘記得差不多了,終究到底還是自己用得太少了,要多實(shí)踐多實(shí)踐。
1、首先上圖(圖片來源于他人的博客,盜圖1枚)
這里寫圖片描述

從這張圖我們可以看到觸及到消息機(jī)制的1些類,比如Looper、Message、MessageQueue、Handler等,和里面的成員變量和方法。下面我們來學(xué)習(xí)1下這幾個(gè)類。

Message:
what : what this message is about.用戶自定義的消息碼,以便接受者可以辨認(rèn)。每一個(gè)Handler 對(duì)消息碼有自己的命名空間,所以不用擔(dān)心和其他的handler沖突。在消息處理中,我們可以根據(jù)這個(gè)字段的不同的值進(jìn)行不同的處理。
arg1和arg2 :這兩個(gè)參數(shù)是為了減小開消的替換物,就是你要是使用setData()寄存少數(shù)幾個(gè)整型數(shù)值的話。
obj : 發(fā)送給接收者的任意對(duì)象。當(dāng)我們使用Messenger跨進(jìn)程發(fā)送消息的時(shí)候,如果是Parcelable框架類的話必須是非空的。對(duì)1般的數(shù)據(jù)1般使用setData()傳遞。
target : 處理消息的handler。
when :消息甚么時(shí)候入隊(duì)列,甚么時(shí)候提交,甚么時(shí)候回收這樣的標(biāo)志吧。
callback : handler發(fā)送消息的時(shí)候可以post1個(gè)runnable對(duì)象,會(huì)觸發(fā)回調(diào)。
next:下1個(gè)消息,看代碼我們知道消息是以鏈表1樣的情勢(shì)存儲(chǔ)的,而消息對(duì)列是以對(duì)列的方式處理消息,先進(jìn)入的消息先處理
obtain() : 推薦使用這樣的方式取得消息對(duì)象,效力會(huì)更高
recycle() : 當(dāng)消息處理完后,回收消息對(duì)象

MessageQueue
MessageQueue類提供1個(gè)消息隊(duì)列,和插入、刪除和提取消息的函數(shù)接口。
mPtr : 通過這個(gè)變量保存1個(gè)Native層的NativeMessageQueue對(duì)象
mMessages : 保存接收到的Message消息。
mQuitAllowed: 是不是允許終止,如果允許的話該值為true。

void quit(boolean safe) { if (!mQuitAllowed) { throw new IllegalStateException("Main thread not allowed to quit."); } synchronized (this) { if (mQuitting) { return; } mQuitting = true; if (safe) { removeAllFutureMessagesLocked(); } else { removeAllMessagesLocked(); } // We can assume mPtr != 0 because mQuitting was previously false. nativeWake(mPtr); } }

mQuitting : 是不是終止了。

private boolean isPollingLocked() { // If the loop is quitting then it must not be idling. // We can assume mPtr != 0 when mQuitting is false. return !mQuitting && nativeIsPolling(mPtr); }

mBlocked:是不是正在等待被激活以獲得消息。
1個(gè)線程最多只可以具有1個(gè)MessageQueue,安卓中通過ThreadLocal來保證1個(gè)線程中最多有1個(gè)Looper

Looper
Threads by default do not have a message loop associated with them.線程默許情況下是沒有消息循環(huán)的。實(shí)現(xiàn)Thread的消息循環(huán)和消息派發(fā),缺省情況下Thread是沒有這個(gè)消息循環(huán)的既沒有Looper;
需要主動(dòng)去創(chuàng)建,然后啟動(dòng)Looper的消息循環(huán)loop;與外部的交互通過Handler進(jìn)行;Looper 的構(gòu)造函數(shù)很簡單,創(chuàng)建MessageQueue,保存當(dāng)前線程到 mThread 中。但它是私有的,只能通過兩個(gè)靜態(tài)函數(shù) prepare()/prepareMainLooper() 來調(diào)用。
mQueue : 消息對(duì)列
prepare() : 初始化當(dāng)前線程作為Looper。在調(diào)用loop()之前1定要先履行這個(gè)方法。知道調(diào)用了quite這個(gè)方法。

This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.

public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }

void prepareMainLooper()
初始化當(dāng)前線程為looper,并且使其作為程序的主looper。通常是由程序根據(jù)環(huán)境創(chuàng)建的,所以開發(fā)者不建議使用這個(gè)方法。

public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }

myLooper()
取得當(dāng)前線程的looper,sThreadLocal是 ThreadLocal sThreadLocal 。ThreadLocal保證了1個(gè)線程里面只有1個(gè)Looper對(duì)象。關(guān)于ThreadLocal的原理大家可以到網(wǎng)上找點(diǎn)資料看1下,有點(diǎn)類似根據(jù)id尋覓值。

public static @Nullable Looper myLooper() { return sThreadLocal.get(); }

loop()
這個(gè)類中最重要的1個(gè)方法。讓Looper開始工作從消息隊(duì)列里取消息,處理消息Looper對(duì)象通過MessageQueue來寄存消息和事件。1個(gè)線程只能有1個(gè)Looper,對(duì)應(yīng)1個(gè)MessageQueue

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.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); } }

void quit()
Quits the looper

public void quit() { mQueue.quit(false); }

Handler
mLooper : 線程的消息處理循環(huán),其實(shí)不是每個(gè)線程都有消息處理循環(huán)。1般開發(fā)中用得比較多的是1個(gè)有Looper的Thread實(shí)現(xiàn),HandlerThread。
mQueue : 消息對(duì)列對(duì)象,是成員對(duì)象mLooper的成員變量。

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

mCallback 提供了另外一種使用Handler 的簡便途徑:只需實(shí)現(xiàn)回調(diào)接口 Callback,而無需子類化Handler。mAsynchronous 是標(biāo)識(shí)是不是異步處理消息

obtainMessage()
從消息池返回1個(gè)新的消息對(duì)象。實(shí)際上就是調(diào)用Message.obtain();

public final Message obtainMessage() { return Message.obtain(this); }

boolean sendMessage(Message msg)
將消息push到消息對(duì)列里面所有等待消息的最后面,在規(guī)定的時(shí)間內(nèi),線程里面的handler會(huì)遭到這個(gè)消息。

public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }

boolean post(Runnable r)
將Runnable對(duì)象添加到消息對(duì)列里面,這個(gè)Runnable對(duì)象將被該線程的handler處理。如果成功添加到消息對(duì)列里面的話返回true。失敗返回false,失敗通常是looper處理的這個(gè)消息正在對(duì)列中退出。

public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }

void dispatchMessage(Message msg)
顧名思義這個(gè)方法是處理消息的。會(huì)根據(jù)不同的條件調(diào)用不同的函數(shù)。在傳入的這個(gè)Message對(duì)象履行Message.obtain()的時(shí)候會(huì)對(duì)msg.callback進(jìn)行賦值。

public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }

所以在查看消息處理對(duì)應(yīng)的函數(shù)時(shí),要看消息是不是是通過obtain()取得的,如果是那末消息處理就會(huì)交由傳遞參數(shù)中callback.run()來處理。而mCallback 則是在實(shí)例化Handler的時(shí)候初始化賦值的。如果msg.callback == null,且 mCallback == null,則由Handler本身的handleMessage()來處理。

**在判斷調(diào)用哪一個(gè)消息處理函數(shù)時(shí),1定要先看是不是在調(diào)用obtain構(gòu)造消息的時(shí)候是否是傳遞了msg或Runable參數(shù),如果沒有,則判斷在構(gòu)造Handler時(shí)是不是將
Callback 函數(shù)當(dāng)作參數(shù)傳遞了進(jìn)來,最后再看自己的Handler是不是重寫了handleMessage函數(shù)。**

void handleMessage(Message msg)
子類必須實(shí)現(xiàn)這個(gè)方法,去接收消息,然后再進(jìn)行1些處理。

public void handleMessage(Message msg) { }

**> MessageQueue作為1個(gè)容器,保存了所有待履行的消息。

MessageQueue中的Message包括3種類型:普通的同步消息,Sync barrier(target = null),異步消息(isAsynchronous() = true)。
MessageQueue的核心函數(shù)為enqueueMessage和next,前者用于向容器內(nèi)添加Message,而Looper通過后者從MessageQueue中獲得消息,并實(shí)現(xiàn)無消息情況下的等待。
MessageQueue把Android消息機(jī)制的Java實(shí)現(xiàn)和C++實(shí)現(xiàn)聯(lián)系起來。
 每一個(gè)線程最多可以有1個(gè)Looper。
每一個(gè)Looper有且唯一1個(gè)MessageQueue
每一個(gè)Handler關(guān)聯(lián)1個(gè)MessageQueue,由該MessageQueue關(guān)聯(lián)的Looper履行(調(diào)用Hanlder.dispatchMessage)
每一個(gè)MessageQueue可以關(guān)聯(lián)任意多個(gè)Handler
Looper API的調(diào)用順序:Looper.prepare >> Looper.loop >> Looper.quit
Looper的核心函數(shù)是Looper.loop,1般loop不會(huì)返回,直到線程退出,所以需要線程完成某個(gè)work時(shí),請(qǐng)發(fā)送消息給Message(或說Handler)**
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 国产精品久久久久久久妇女 | 黄色一级大片在线免费看产 | 99精品视频在线观看免费播放 | 久久久精品网 | 国产欧美一区二区精品性色 | 欧美日韩一区二区精品 | 黄色网址电影 | 国产午夜视频在线观看 | 国产传媒一区 | 中文字幕精品久久久久 | 毛片视频免费 | 爱情岛论坛首页网址 | 欧美天堂 | 福利在线观看 | 色综合网在线 | 亚洲欧洲无码一区二区三区 | 国产精品美女视频 | 国产精品18hdxxxⅹ在线 | 久久久久久久成人 | 国产欧美日韩综合精品 | 国产精品久久久久7777按摩 | 99精品视频免费观看 | 91精品一区二区三区久久久久久 | 黄色毛片免费看 | 国产精品一区二区三 | 亚洲精品aⅴ中文字幕乱码 97视频免费在线 | 成年免费在线视频 | 久久久网站免费 | 国产精品久久久久久久 | 一级黄色免费毛片 | 国产成人久久精品 | 亚洲欧美激情精品一区二区 | 亚洲精品欧美一区二区三区 | 久久av免费看 | 天天插日日干 | 懂色av 粉嫩av 蜜乳av | 久久婷婷亚洲 | 成人一区二区三区 | 日韩精品中文字幕一区二区 | av中文在线资源 | 免费aaa级毛片在线视频 |