Handler的理解、用法以及运行机制原理
一、Handler是什么?
Handler在我們android開發中是一項非常重要的機制,那Handler是什么呢?Handler是android提供用于更新UI的一套機制,也是消息處理機制。
Handler的主要作用有兩個:
??????? (1).在新啟動的線程中發送消息
?????????????????? ?(2).在主線程中獲取,處理消息。
解釋:(1) 當應用程序啟動時,Android首先會開啟一個主線程 (也就是UI線程) , 主線程為管理界面中的UI控件, 進行事件分發, 比如說, 你要是點擊一個 Button ,Android會分發事件到Button上,來響應你的操作。 主線程(UI線程)就是android程序從啟動運行到最后的程序。
(2) 如果此時需要一個耗時的操作,例如: 聯網讀取數據,或者讀取本地較大的一個文件的時候,你不能把這些操作放在主線程中,如果你放在主線程中的話,界面會出現假死現象, 如果5秒鐘還沒有完成的話,會收到Android系統的一個錯誤提示? "強制關閉"。
(3)這個時候我們需要把這些耗時的操作,放在一個子線程中,因為子線程涉及到UI更新,Android主線程是線程不安全的, 也就是說,更新UI只能在主線程中更新,子線程中操作是危險的。
(4)這個時候,Handler就出現了。,來解決這個復雜的問題 ,由于Handler運行在主線程中(UI線程中),? 它與子線程可以通過Message對象來傳遞數據, 這個時候,Handler就承擔著接受子線程傳過來的(子線程用sendMessage()方法傳弟)Message對象(里面包含數據)? , 把這些消息放入主線程隊列中,配合主線程進行更新UI。
二、為什么要用Handler
如果我們不用Handler去發送消息,更新UI可以嗎?
答案是不行的。 Android在設計的時候,就封裝了一套消息創建,傳遞,處理機制,如果不遵循這樣的機制,就沒有辦法更新UI信息的,就會拋出異常信息。
拋出異常的描述:不能在非UI線程中去更新UI
三、 Handler怎么用
?handler可以分發Message對象和Runnable對象到主線程中,每個Handler實例,都會綁定到創建他的線程中(一般是位于主程),它有兩個作用:
?????? ?(1)合理調度安排消息和runnable對象,使它們在將來的某個點被執行.
??????? (2)安排一個動作在不同的線程中執行
Handler中開啟線程和分發消息的一些方法:
????? post(Runnable)直接開啟Runnable線程
????? postAtTime(Runnable,long)在指定的時間long,開始啟動線程
????? postDelayed(Runnable long)在延遲long時間后,啟動Runnable線程
????? sendEmptyMessage(int) 發送指定的消息,通過參數int來區分不同的消息
????? sendMessage(Message)發送消息到UI線程中
????? sendMessageAtTime(Message,long)???? 這個long代表的是系統時間,不推薦用
?????sendMessageDelayed(Message,long)??? 此方法long代表調用后幾秒后執行。
?? sendMessage類方法, 允許你安排一個帶數據的Message對象到隊列中,等待更新.
handler基本使用:?1)在主線程中,使用handler很簡單,new一個Handler對象實現其handleMessage方法,在 handleMessage?中提供收到消息后相應的處理方法即可。(接收消息,并且更新UI)
???????????????????? 2)在新啟動的線程中發送消息
示例:
public class HandlerActivity extends AppCompatActivity {private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);tv.setText("msg.arg1:"+msg.arg1+"--msg.arg2:"+msg.arg2);}};private TextView tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_handler);initView();new Thread(new Runnable() {@Overridepublic void run() {Message msg = new Message();//實例化消息對象msg.arg1 = 99;//攜帶參數msg.arg2 = 100;//攜帶參數Object str = new Object();//實例化對象msg.obj = str; //攜帶參數為實體類對象}});}private void initView() {tv = (TextView) findViewById(R.id.tv);} }handler運行機制:
?
?
?Handler機制也可叫異步消息機制,它主要由4個部分組成:Message,Handler,MessageQueue,Looper,在上面圖中我們已經有了大致印象,接下來我們對4個成員進行著重的了解:
1.Message
??Message是在線程之間傳遞的消息,它可以在內部攜帶少量的信息,用于在不同線程之間交換數據。使用Message的arg1和arg2便可攜帶int數據,使用obj便可攜帶Object類型數據。
2.Handler
??Handler顧名思義就是處理者的意思,它只要用于在子線程發送消息對象Message,在UI線程處理消息對象Message,在子線程調用sendMessage方法發送消息對象Message,而發送的消息經過一系列地輾轉之后最終會被傳遞到Handler的handleMessage方法中,最終在handleMessage方法中消息對象Message被處理。
3.MessageQueue
??MessageQueue就是消息隊列的意思,它只要用于存放所有通過Handler發送過來的消息。這部分消息會一直存放于消息隊列當中,等待被處理。每個線程中只會有一個MessageQueue對象,請牢記這句話。其實從字面上就可以看出,MessageQueue底層數據結構是隊列,而且這個隊列只存放Message對象。
4.Looper
??Looper是每個線程中的MessageQueue的管家,調用Looper的loop()方法后,就會進入到一個無限循環當中,然后每當MesssageQueue中存在一條消息,Looper就會將這條消息取出,并將它傳遞到Handler的handleMessage()方法中。每個線程只有一個Looper對象。
??了解了上述Handler機制的4個成員后,我們再來把思路理一遍:首先在UI線程我們創建了一個Handler實例對象,無論是匿名內部類還是自定義類生成的Handler實例對象,我們都需要對handleMessage方法進行重寫,在handleMessage方法中我們可以通過參數msg來寫接受消息過后UIi線程的邏輯處理,接著我們創建子線程,在子線程中需要更新UI的時候,新建一個Message對象,并且將消息的數據記錄在這個消息對象Message的內部,比如arg1,arg2,obj等,然后通過前面的Handler實例對象調用sendMessge方法把這個Message實例對象發送出去,之后這個消息會被存放于MessageQueue中等待被處理,此時MessageQueue的管家Looper正在不停的把MessageQueue存在的消息取出來,通過回調dispatchMessage方法將消息傳遞給Handler的handleMessage方法,最終前面提到的消息會被Looper從MessageQueue中取出來傳遞給handleMessage方法,最終得到處理。這就是Handler機制整個的工作流程。應該都差不多懂了吧,感覺我寫的很接地氣啊。
Handler運行源碼篇
?
總結
以上是生活随笔為你收集整理的Handler的理解、用法以及运行机制原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决GREENPLUM某些版本gprec
- 下一篇: 425 Failed to establ