摘要:關于中的消息機制就進行到這里,下一篇將講講中的內存泄漏問題以及處理方法。
這幾天對handler有一些研究,寫出來供大家看看。 一、消息機制詳解 Android程序中,主要是通過消息機制來推動整個程序運作的。而消息機制中,完成主要功能的主要有以下幾個類: 1、Looper 2、Message、MessageQueue 3、handler 這是最基礎的幾個消息機制類,下面探究一下這幾個類如何完成Android消息機制的運行。 首先看Message和MessageQueue。Message顧名思義,是消息機制中消息的載體,繼承Parcelable序列化接口,可以在進程和組件之間作為消息的載體傳播消息。而MessageQueue就是承載message的隊列。關于Message,主要有以下幾點總結: 1、Message中是持有Handler對象,作為Message的target的。這也很好理解,為了發送消息給handler嘛~這里要注意的一點是,Message中持有handler,而handler一般是持有Context的,所以這里是有可能引發內存泄漏的,后面會對這點進行進一步講解。
有了target之后,message就可以調用:
還有
public void sendToTarget() {
target.sendMessage(this);
} //發送消息到target handler
2、Message中有四個參數:
public int what
public int arg1
public int arg2
public Object obj
what參數是消息的識別碼,用于給handler判斷不同的Message,采取不同的處理方法,這個不用多說了。
arg1和arg2都是一些攜帶在message中的int消息,相比setData(bundle)更加輕量級。
obj是message中可以承載的對象,注意要實現Parcelable接口。
3、Message中的recyle方法是用于當message被消費后,對message進行回收的。這個方法也蠻重要的,正是因為message會自己回收自己,才避免了很多內存泄漏的問題。
4、接下來看看MessageQuene。MessageQueue是承載Message的隊列,其中最重要的方法是next方法,這個方法的作用是返回隊列中下一個message。
接下來看看Looper。Looper我覺得是消息機制中最核心的類,起到了推動整個消息機制運行的作用。 looper中的主要有以下四個方法: public static prepare(); public static myLooper(); public static loop(); public void quit(); prepare方法代碼如下:
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));
}
這個方法可以理解為為本現場初始化隊列消息,每個線程要使用looper進行消息循環時,都要先調用perpare方法。 myLooper方法用于返回當前消息隊列的線程。注意,一個消息隊列只能有一個線程。 Looper中最重要的是loop方法,調用這個方法,整個隊列遍開始循環。下面看看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
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
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();
}
}
可以看到,loop方法中不斷地從消息隊列mQueue中去獲取下一個要處理的消息msg,如果消息的target成員變量為null,就表示要退出消息循環了 否則的話就要調用這個target對象的dispatchMessage成員函數來處理這個消息,這個target對象的類型為Handler 在上面的代碼中,msg調用了它的target的dispatchMessage方法,實際上就是將msg丟給handler去處理了(實際上handler也沒有處理,是提供接口給實現了handleMessage的具體事務類去處理)。 接下來看看Handler。Handler主要分為SendMessage和HandleMessage兩個方法,分別是發送msg和處理msg。 SendMessage方法代碼如下:
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
重點在最后一行加粗的代碼,就是把msg裝進msgqueue隊列中(message肯定是持有messageQueue對象的廢話)。其實發送消息實際上,也就是把消息裝進消息隊列中而已,因為前面的loop方法已經在不斷的循環的讀取msgqueue中的消息,只要把消息加進messagequeue中,就可以是消息得到處理。 再來看看消息是怎樣被處理的:
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
這里可以看到,實際上handler是沒有處理msg的,而是給繼承了handler的具體類,實現handlermessage,并對消息做出相應的處理。 我們可以看出,handler實際上并沒有做什么事情,只是提供回調接口,給具體的類去實現。在使用handler的時候,可以讓具體處理msg的類繼承handler.Callback接口,實現handleMessage方法去處理消息。 關于Android中的消息機制就進行到這里,下一篇將講講handler中的內存泄漏問題以及處理方法。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64413.html
今年3月,Google 破天荒提前半年發布了 Android N 開發者預覽版。當然,作為一個不合格的谷粉并沒有第一時間體驗安裝,因為至今仍然能夠回憶起來去年今日此門中(霧)興沖沖刷了 Android M Preview 的時候發現各種 Crash 就連微信也(不出所料得)中招時自己一臉懵逼的心情。當然,為自己的機智而慶幸并沒有過多久,很快就有微信好友(當然也是純純的谷粉)反饋微信又雙叒叕在 An...
摘要:如何挑選合適的導航結構導航設計是應用設計的關鍵,設計規范以下簡稱規范中將導航元素分為對等層次和歷史導航等幾類,例如表和透視表導航窗格是對等導航元素,中心大綱細節屬于分層導航元素,返回則屬于歷史導航元素。 此文已由作者楊凱明授權網易云社區發布。 歡迎訪問網易云社區,了解更多網易技術產品運營經驗。 繼Windows 10系統發布之后,很多Windows用戶更新了系統。win10系統的發布,...
閱讀 3779·2021-09-02 09:53
閱讀 2758·2021-07-30 14:57
閱讀 3505·2019-08-30 13:09
閱讀 1207·2019-08-29 13:25
閱讀 818·2019-08-29 12:28
閱讀 1463·2019-08-29 12:26
閱讀 1139·2019-08-28 17:58
閱讀 3316·2019-08-26 13:28