android消息機制,異步和多線程java
在xxxx1.92正式版的時候付費購買曾單獨封裝了一個流程PaymentFlow並繼承於Handler,調用方只要依據這個流程建立流程實例並觸發開始,實例便可依據設定的支付流程完成.但在異步和多線程方面卻有’ java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()’的問題.最近在做風網絡庫的替換,網絡庫使用的Handler的繼承類MessageHandler做爲回調.一樣也存在多線程的異步調用或諸塞的問題,因此在此就將Handler的機制在研究一遍.android
Android應用程序是消息驅動的,並經過Looper,Handler來實現消息循環機制,且是針對線程的. 一個線程能夠存在(固然也能夠不存在)一個消息隊列和一個消息循環(Looper),特定線程的消息只能分發給本線程,不能進行跨線程,跨進程通信.可是建立的工做線程默認是沒有消息循環和消息隊列的,若是想讓該線程具備消息隊列和消息循環,須要在線程中首先調用Looper.prepare()來建立消息隊列,而後調用Looper.loop()進入消息循環. Handler的做用是把消息加入特定的(Looper)消息隊列中,並分發和處理該消息隊列中的消息.構造Handler的時候能夠指定一個Looper對象,若是不指定則利用當前線程的Looper建立.Activity是一個UI線程,運行於主線程中,Android系統在啓動的時候會爲Activity建立一個消息隊列和消息循環(Looper).一個Activity中能夠建立多個工做線程或者其餘的組件,若是這些線程或者組件把他們的消息放入Activity的主線程消息隊列,那麼該消息就會在主線程中處理了.之間的關係以下圖所示安全
咱們能夠寫個測試用例在Activity和Handler中分別打印出線程編號就明白在默認狀況下(例如: private Handler handler = new Handler();),Activity和Handler是在同個線程上運行的.網絡
若是一個線程中調用Looper.prepare(),那麼系統就會自動的爲該線程創建一個消息隊列,而後調用 Looper.loop();以後就進入了消息循環,這個以後就能夠發消息、取消息、和處理消息.這個如何發送消息和如何處理消息能夠在其餘的線程中經過Handle來作,但前提是咱們的Hanle知道這個子線程的Looper,可是你若是不是在子線程運行 Looper.myLooper(),通常是得不到子線程的looper的.多線程
除此也能夠經過建立HandlerThread來爲Handler來建立一個新得的Looper並賦予Handler,這樣Handler就會在非主線程執行.併發
HandlerThread thread=new HandlerThread(「handler_thread」));異步
thread.start();ide
Handler m=new Handler(thread.getLooper());工具
Handler與調用者處於同一線程,若是Handler裏面作耗時的動做,調用者線程會阻塞.Android UI操做不是線程安全的,而且這些操做必須在UI線程中執行.Android提供了幾種基本的能夠在其餘線程中處理UI操做的方案,包括Activity 的runOnUiThread(Runnable),View的post以及1.5版本的工具類AsyncTask等方案都採用了 Handler,Handler的post對線程的處理也不是真正start一個新的線程,而是直接調用了線程的run方法.oop
一個Looper 只有處理完一條Message纔會讀取下一條,因此消息的處理是阻塞形式的.可是若是用不一樣的Looper則能達到併發的目的.Service 中,onStart的執行也是阻塞的.若是一個startService在onStart執行完成以前,再次條用startService也會阻塞.若是但願能儘快的執行onStart則能夠在onStart中使用handler,由於Message的send是非阻塞的.若是要是不一樣消息的處理也是併發 的,則能夠用不一樣的Looper實例化Handler.
向Handler對象發送相似new Message()形式的空Message能夠達到清空Message的目的,這種作法與getLooper().quit()的作法是同樣的.若是利用的資源較多,應及時清理.