Handler post(Runnable runnable)和sendMessage(Message msg)的區別比較
先上Handler的原始碼看一下:
無聊的原始碼copy,可以看到最終都是呼叫的最後一個建構函式,Android原始碼裡面到處都是這種寫法,接下來我們要講的sendMessage也是這種寫法。這樣寫的好處是,我們不用關心過多的引數,靈活適配各種不同的需求。來看下初始化的三個屬性,Looper:上面有說,Handler與建立它的執行緒的訊息佇列是繫結的,實際上Handler收發訊息的三要素Handler、MessageQueue、Looper,是缺一不可的,執行緒必須有Looper,才能從MessageQueue裡把訊息取出來,所以一定要建立Looper才能使用Handler,剛剛的例子我們並沒有看到Looper建立,而我們之所以能夠在Activity裡直接使用Handler是因為主執行緒,也叫UI執行緒、ActivityThread被建立的時候會初始化一個Looper。所以我們能夠在UI執行緒裡直接使用Looper(因為更新UI使用的多,而且Android整個視窗的UI更新都是用的Handler機制)。Callback:介面,回撥用來寫收到訊息後處理訊息的程式碼。async:傳給訊息的一個boolean型變數,是否需要同步。
直接來看我們最熟悉的sendMessage的方法:
最普通的傳送訊息,其內部使用了延時傳送,延時設為0. 這是Android裡面常用的模式,這樣做的好處是當你不需要傳引數的時候可以直接使用無參的,使用方便,而且內部減少
了程式碼量,避免再重複寫一個傳送訊息的實現。
傳送一個空訊息只需要傳遞一個訊號,用訊息型別就足夠攜帶我們要傳遞的資訊。同樣呼叫了它的延時傳送方法,延時為0.
我們可以看到,系統同樣是通過傳送Message物件來實現的傳送空訊息。這個物件值承載了我們設定的What資訊。它最終調的也是 sendMessageDelayed(msg, delayMillis);延時傳送一個訊息。這裡用了 Message.obtain();這是一種單例模式,避免每傳送一個訊息就new出一個物件,如果這樣記憶體佔用會很高,而且沒有必要。在講Message的時候會講到。
這是一個定時在某個確定的時刻傳送空訊息的方法,內部同樣呼叫了傳送訊息對應的方法。如果我們猜想的話,這個確定時刻傳送同樣可以用延時傳送訊息的方法來實現,只需要計算確定的那個時刻和當前時間的差值,然後把這個差值設為延時引數即可。後面來驗證我們的猜想是否正確。
看了這個方法,我們突然有一種被耍的趕腳,原來不是定時傳送調了延時傳送,而是延時傳送內部調了定時傳送,哈哈,這樣也可以解釋,因為他們本身就可以通過當前時間相互來轉化。這裡把當前時間加上延時時間,來計算要傳送訊息的時刻,最終用定時傳送來實現。
可以看到這個才是真正的傳送了一條訊息的方法,上面的所有傳送訊息的方法最終都是要調這個方法。在傳送訊息的最後又呼叫了這個enqueueMessage(queue, msg, uptimeMillis);從名字看,我們大概可以猜到,這裡應該是把訊息和訊息確切的傳送時間,塞到訊息佇列裡面。稍有開發經驗的都知道,把訊息塞給佇列這種事理論上應該交個MessageQueue來提供一個方法比較合理,Android為什麼這麼搞呢?我們帶著這個疑問來看Handler提供的這個方法:
這裡可以看到這裡這個方法並沒有做什麼事,只是給Message的target屬性賦值,表示這個訊息的接收者是自己,這不就是Handler自己發訊息給自己的判斷標識麼。。。mAsynchronous這個值是表示是否是同步的,是在Handler構造方法裡傳進來的。最後又把這個屬性塞給了Message,讓Message自己處理是否同步的問題。後面調了MessageQueue的enqueueMessage方法,到這裡Handler訊息的傳送過程也就結束了。(多說一句,這裡傳的時間,其實是用來排序的,Message裡面有一個long型的屬性when,就是Message的時間標籤,最終這裡傳入的uptimeillis會賦值給msg的when屬性,讓MessageQueue用來根據時間對所有插入Message進行排隊,構成一個單連結串列。存放訊息和迴圈用。為什麼用連結串列,資料不停的再插入刪除什麼的操作,所以用連結串列,Android真屌,我平時都注意不到這些小細節,自己上去就亂搞。在MessageQueue的原始碼裡可以看到這個過程,這裡就不再講述了,因為我們平常也不和MessageQueue直接打交道)
和這個和上面的方法基本一樣就是設定了時間為0,表示在排隊時把它塞到佇列的最前端。不多講了。
postRunnable的所有方法:
這裡放一塊兒說,可以明顯看到,post系列的所有方法,立即post,定時post,延時post方法裡面都是呼叫的sedMessage系列的對應的方法。而一個明顯的標誌就是Message引數都是把Runnable物件傳給getPostMessage(r)返回了一個Message物件,如果沒猜錯,這貨又是把Runnable賦給Message裡面的一個Runnable屬性。來看這個方法:
就知道,果然不出所料,Message裡面有一個叫callback的Runnable屬性。這樣是不是很完美呢,無論你send一個Message,還是post一個Runnnable,最終都是send一個Message。然後我把Runnable放到Message的Runnnable屬性裡面,接到Message再拿出來,就這麼簡單。
Handler傳送訊息的過程是向訊息佇列中插入一條訊息,MessageQueue的next方法就會返回這條訊息給Looper,Looper收到這條訊息之後就開始處理了,最終訊息由looper交由Handler處理,即Handler的dispatchmessage方法會被呼叫,這是Handler就進入處理訊息的階段。
1.一個Handler只有一個佇列;
2.在呼叫Handler.post(Runnable runnable)方法時,會將runnable封裝成一個Message;
3.在佇列執行時,會判斷當前是否封裝了Runnable,如果封裝了,就直接執行Runnable,如果沒有,將當前的Message傳遞給handlerMessage(Message msg)處理;
4.Handler在例項化的時候可以設定一個callback<Handler.Callback>,callback也有一個HandlerMessage(Message msg)方法,如果步驟3中的Handler有callback,那麼呼叫的是callback的HandlerMessage(message msg),否則呼叫自身的handlerMessage(Message msg)方法。
首先,檢查Message的callback是否為null,不為空就通過handleCallback來處理訊息。message的callback是一個Runnbale物件,實際上就是Handler的post方法所傳遞的Runnable引數。
其次,檢查mCallback是否為空,不為null即呼叫mCallback的handlerMessage方法來處理訊息
相關文章
- Thread和Runnable的區別thread
- Thread 和runnable的區別thread
- Android中Handler Runnable與Thread的區別詳解Androidthread
- Java中Runnable和Thread的區別Javathread
- Java 中Thread 和Runnable的區別Javathread
- java執行緒系列---Runnable和Thread的區別Java執行緒thread
- Runnable jarJAR
- 使用Thread類和Runnable介面實現多執行緒的區別thread執行緒
- new Handler().postDelayed(new Runnable())是否執行在主執行緒?執行緒
- 從Handler.post(Runnable r)再一次梳理Android的訊息機制(以及handler的記憶體洩露)Android記憶體洩露
- 大話Android多執行緒(一) Thread和Runnable的聯絡和區別Android執行緒thread
- (十三) 說一下runnable 和 callable 有什麼區別?Future是什麼?
- java.lang.Runnable介面Java
- 併發-2-Thread和Runnable的APIthreadAPI
- Java中Thread 和Runnable 深入理解Javathread
- AsyncTask和Handler的區別
- Thread是如何處理Runnable的thread
- Vue和微信小程式的區別、比較Vue微信小程式
- 溫故知新----執行緒之Runnable與Callable介面的本質區別執行緒
- GET和POST的區別?
- GET和POST的區別
- GET 和 POST 的區別
- POST 和 GET 的區別
- Hibernate和Ibatis區別和比較BAT
- PostMessage與SendMessage區別
- get和post區別
- http和https的區別/get和post的區別HTTP
- Runnable介面實現多執行緒執行緒
- Runnable,Callable,Future關係淺析
- 使用Runnable介面實現執行緒的方法執行緒
- Thread(Runnable xxx)中的問題thread
- JAVA中字串比較equals()和equalsIgnoreCase()的區別Java字串
- $GLOBALS['HTTP_RAW_POST_DATA']和$_POST的區別HTTP
- 搞懂Runnable Callable Future FutureTask 及應用
- 匿名內部類中關於new Runnable ( )
- ajax中get和post的區別
- Spring和SpringBoot比較,解惑區別Spring Boot
- http中的get和post的區別HTTP