多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > Android消息機制

Android消息機制

來源:程序員人生   發布時間:2016-11-29 09:00:38 閱讀次數:2532次

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

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

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

MessageQueue
MessageQueue類提供1個消息隊列,和插入、刪除和提取消息的函數接口。
mPtr : 通過這個變量保存1個Native層的NativeMessageQueue對象
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個線程最多只可以具有1個MessageQueue,安卓中通過ThreadLocal來保證1個線程中最多有1個Looper

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

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()
初始化當前線程為looper,并且使其作為程序的主looper。通常是由程序根據環境創建的,所以開發者不建議使用這個方法。

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()
取得當前線程的looper,sThreadLocal是 ThreadLocal sThreadLocal 。ThreadLocal保證了1個線程里面只有1個Looper對象。關于ThreadLocal的原理大家可以到網上找點資料看1下,有點類似根據id尋覓值。

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

loop()
這個類中最重要的1個方法。讓Looper開始工作從消息隊列里取消息,處理消息Looper對象通過MessageQueue來寄存消息和事件。1個線程只能有1個Looper,對應1個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 : 線程的消息處理循環,其實不是每個線程都有消息處理循環。1般開發中用得比較多的是1個有Looper的Thread實現,HandlerThread。
mQueue : 消息對列對象,是成員對象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 的簡便途徑:只需實現回調接口 Callback,而無需子類化Handler。mAsynchronous 是標識是不是異步處理消息

obtainMessage()
從消息池返回1個新的消息對象。實際上就是調用Message.obtain();

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

boolean sendMessage(Message msg)
將消息push到消息對列里面所有等待消息的最后面,在規定的時間內,線程里面的handler會遭到這個消息。

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

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

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

void dispatchMessage(Message msg)
顧名思義這個方法是處理消息的。會根據不同的條件調用不同的函數。在傳入的這個Message對象履行Message.obtain()的時候會對msg.callback進行賦值。

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

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

**在判斷調用哪一個消息處理函數時,1定要先看是不是在調用obtain構造消息的時候是否是傳遞了msg或Runable參數,如果沒有,則判斷在構造Handler時是不是將
Callback 函數當作參數傳遞了進來,最后再看自己的Handler是不是重寫了handleMessage函數。**

void handleMessage(Message msg)
子類必須實現這個方法,去接收消息,然后再進行1些處理。

public void handleMessage(Message msg) { }

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

MessageQueue中的Message包括3種類型:普通的同步消息,Sync barrier(target = null),異步消息(isAsynchronous() = true)。
MessageQueue的核心函數為enqueueMessage和next,前者用于向容器內添加Message,而Looper通過后者從MessageQueue中獲得消息,并實現無消息情況下的等待。
MessageQueue把Android消息機制的Java實現和C++實現聯系起來。
 每一個線程最多可以有1個Looper。
每一個Looper有且唯一1個MessageQueue
每一個Handler關聯1個MessageQueue,由該MessageQueue關聯的Looper履行(調用Hanlder.dispatchMessage)
每一個MessageQueue可以關聯任意多個Handler
Looper API的調用順序:Looper.prepare >> Looper.loop >> Looper.quit
Looper的核心函數是Looper.loop,1般loop不會返回,直到線程退出,所以需要線程完成某個work時,請發送消息給Message(或說Handler)**
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国内精品视频免费观看 | 欧美精品一区二区在线观看 | 91porn国产在线观看 | 男人边吃奶边做性视频 | 欧美一级毛级毛片 | 国内成人精品亚洲日本语音 | 一级毛片免费观看 | 日韩一级在线播放免费观看 | 色cccwww在线播放| 欧美激情五月 | 免费欧洲毛片a级视频无风险 | 日本一区二区高清免费不卡 | 国产在线欧美日韩精品一区二区 | 日本aa在线| 久久一区二区三区不卡 | 国产资源视频 | 国产最新精品2020好看的 | 曰曰碰天天碰国产 | 欧美一区永久视频免费观看 | 国产高清在线免费观看 | 欧美日韩精品一区二区在线线 | 亚洲人视频在线观看 | 欧美日韩国产精品自在自线 | 免费视频网站一级人爱视频 | 国产美女亚洲精品久久久久久 | 欧美日韩国产精品自在自线 | 免费网站在线播放 | 视色4setv.com| 免费在线h视频 | 久久精品国内偷自一区 | 国产免费高清在线精品一区 | 国产精品日韩一区二区三区 | 精品三区 | 春暖花开亚洲性无区一区二区 | 18到20岁女人一级毛片 | 久久男人精品 | 精品伊人久久久香线蕉 | 中文字幕在线资源 | 麻豆精品国产免费观看 | 成人在线精品视频 | 久久久久国产一级毛片高清片 |