androidHandler讲解
一、Handler的定義:
????????? 主要接受子線程發送的數據,并用此數據配合主線程更新UI.
????????? 解釋:當應用程序啟動時,Android首先會開啟一個主線程 (也就是UI線程) , 主線程為管理界面中的UI控件,進行事件分發,比如說, 你要是點擊一個 Button, Android會分發事件到Button上,來響應你的操作。??如果此時需要一個耗時的操作,例如:聯網讀取數據,或者讀取本地較大的一個文件的時候,你不能把這些操作放在主線程中,如果你放在主線程中的話,界面會出現假死現象,如果5秒鐘還沒有完成的話,會收到Android系統的一個錯誤提示??"強制關閉".??這個時候我們需要把這些耗時的操作,放在一個子線程中,因為子線程涉及到UI更新,Android主線程是線程不安全的,也就是說,更新UI只能在主線程中更新,子線程中操作是危險的.這個時候,Handler就出現了來解決這個復雜的問題,由于Handler運行在主線程中(UI線程中),它與子線程可以通過Message對象來傳遞數據,這個時候,Handler就承擔著接受子線程傳過來的(子線程用sedMessage()方法傳弟)Message對象,(里面包含數據)??,把這些消息放入主線程隊列中,配合主線程進行更新UI。
?
二、Handler一些特點
????????handler可以分發Message對象和Runnable對象到主線程中,每個Handler實例,都會綁定到創建他的線程中(一般是位于主線程),
? ?? ???它有兩個作用: (1):??安排消息或Runnable在某個主線程中某個地方執行, (2)安排一個動作在不同的線程中執行
? ?? ?
? ?? ???Handler中分發消息的一些方法
? ?? ???post(Runnable)
? ?? ???postAtTime(Runnable,long)
? ?? ???postDelayed(Runnable long)
? ?? ???sendEmptyMessage(int)
? ?? ???sendMessage(Message)
? ?? ???sendMessageAtTime(Message,long)
? ?? ???sendMessageDelayed(Message,long)
????????以上post類方法允許你排列一個Runnable對象到主線程隊列中,
? ?? ???sendMessage類方法,允許你安排一個帶數據的Message對象到隊列中,等待更新.
三、Handler實例
??????(1) 子類需要繼承Handler類,并重寫handleMessage(Message msg)方法, 用于接受線程數據
??????以下為一個實例,它實現的功能為 :通過線程修改界面Button的內容
?
public class MyHandlerActivity extendsActivity {
????Button button;
????MyHandler myHandler;
?
????protected void onCreate(Bundle savedInstanceState) {
????????super.onCreate(savedInstanceState);
????????setContentView(R.layout.handlertest);
?
????????button = (Button) findViewById(R.id.button);
????????myHandler = new MyHandler();
????????// 當創建一個新的Handler實例時, 它會綁定到當前線程和消息的隊列中,開始分發數據
????????// Handler有兩個作用, (1) : 定時執行Message和Runnalbe 對象
????????// (2): 讓一個動作,在不同的線程中執行.
?
????????// 它安排消息,用以下方法
????????// post(Runnable)
????????// postAtTime(Runnable,long)
????????// postDelayed(Runnable,long)
????????// sendEmptyMessage(int)
????????// sendMessage(Message);
????????// sendMessageAtTime(Message,long)
????????// sendMessageDelayed(Message,long)
??????
????????// 以上方法以 post開頭的允許你處理Runnable對象
????????//sendMessage()允許你處理Message對象(Message里可以包含數據,)
?
????????MyThread m = new MyThread();
????????new Thread(m).start();
????}
?
????/**
????* 接受消息,處理消息 ,此Handler會與當前主線程一塊運行
????* */
?
????class MyHandler extends Handler {
????????public MyHandler() {
????????}
?
????????public MyHandler(Looper L) {
????????????super(L);
????????}
?
????????// 子類必須重寫此方法,接受數據
????????@Override
????????public void handleMessage(Message msg) {
????????????// TODO Auto-generated method stub
????????????Log.d("MyHandler", "handleMessage......");
????????????super.handleMessage(msg);
????????????// 此處可以更新UI
????????????Bundle b = msg.getData();
????????????String color = b.getString("color");
????????????MyHandlerActivity.this.button.append(color);
?
????????}
????}
?
????class MyThread implements Runnable {
????????public void run() {
?
????????????try {
???????????????? Thread.sleep(10000);
????????????} catch (InterruptedException e) {
???????????????? // TODO Auto-generated catchblock
???????????????? e.printStackTrace();
????????????}
?
????????????Log.d("thread.......", "mThread........");
????????????Message msg = new Message();
????????????Bundle b = new Bundle();// 存放數據
????????????b.putString("color", "我的");
????????????msg.setData(b);
?
????????????MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler發送消息,更新UI
?
????????}
????}
?
?
?
?
?
1. 傳遞Message。用于接受子線程發送的數據, 并用此數據配合主線程更新UI。
??? 在Android中,對于UI的操作通常需要放在主線程中進行操作。如果在子線程中有關于UI的操作,那么就需要把數據消息作為一個Message對象發送到消息隊列中,然后,有Handler中的handlerMessge方法處理傳過來的數據信息,并操作UI。當然,Handler對象是在主線程中初始化的,以為它需要綁定在主線程的消息隊列中。
??? 類sendMessage(Message msg)方法實現發送消息的操作。 在初始化Handler對象時重寫的handleMessage方法來接收Messgae并進行相關操作。
??
| ? 1.? //Handler處理子線程消息代碼示例:? 2.? ? 3.? public?class?Activity01?extends?Activity ? 4.? { ? 5.? ????//聲明ProgressBar對象? 6.? ????private?ProgressBar?m_ProgressBar; ? 7.? ????private?ProgressBar?m_ProgressBar2; ? 8.? ????private?Button?mButton01; ? 9.? ????protected?static?final?int?GUI_STOP_NOTIFIER?=?0x108; ? 10.????protected?static?final?int?GUI_THREADING_NOTIFIER?=?0x109; ? 11.????public?int?intCounter=0; ? 12.????/**?Called?when?the?activity?is?first?created.?*/? 13.????@Override? 14.????public?void?onCreate(Bundle?savedInstanceState) ? 15.????{ ? 16.????????super.onCreate(savedInstanceState); ? 17.????????//設置窗口模式,,因為需要顯示進度條在標題欄? 18.????????requestWindowFeature(Window.FEATURE_PROGRESS); ? 19.????????setProgressBarVisibility(true); ? 20.????????setContentView(R.layout.main); ? 21.???????? ? 22.????????//取得ProgressBar? 23.????????m_ProgressBar?=?(ProgressBar)?findViewById(R.id.ProgressBar01); ? 24.????????m_ProgressBar2=?(ProgressBar)?findViewById(R.id.ProgressBar02); ? 25.????????mButton01?=?(Button)findViewById(R.id.Button01);? ? 26.???????? ? 27.????????m_ProgressBar.setIndeterminate(false); ? 28.????????m_ProgressBar2.setIndeterminate(false); ? 29.???????? ? 30.????????//當按鈕按下時開始執行,? 31.????????mButton01.setOnClickListener(new?Button.OnClickListener() ? 32.????????{ ? 33.??????????@Override? 34.??????????public?void?onClick(View?v) ? 35.??????????{ ? 36.????????????//?TODO?Auto-generated?method?stub? 37.?????????????? ? 38.??????????????//設置ProgressBar為可見狀態? 39.??????????????m_ProgressBar.setVisibility(View.VISIBLE); ? 40.??????????????m_ProgressBar2.setVisibility(View.VISIBLE); ? 41.??????????????//設置ProgressBar的最大值? 42.??????????????m_ProgressBar.setMax(100); ? 43.??????????????//設置ProgressBar當前值? 44.??????????????m_ProgressBar.setProgress(0); ? 45.??????????????m_ProgressBar2.setProgress(0); ? 46.? 47.??????????????//通過線程來改變ProgressBar的值? 48.??new?Thread(new?Runnable()?{ ? 49.?????public?void?run() ? 50.????????{ ? 51.?????for?(int?i?=?0;?i?<?10;?i++) ? 52.????????{ ? 53.???????????try? 54.???????????{ ? 55.?????????????????intCounter?=?(i?+?1)?*?20; ? 56.?????????????????Thread.sleep(1000); ? 57.? 58.????????????if?(i?==?4) ? 59.????????????{ ? 60.????????????Message?m?=?new?Message(); ? 61.? 62.?????????????m.what?=?Activity01.GUI_STOP_NOTIFIER; ? 63.????????????Activity01.this.myMessageHandler.sendMessage(m); 64.??//將message發送到消息隊列 ? 65.??????????????break; ? 66.?????????????} ? 67.????????????else? 68.???????????{ ? 69.???????????Message?m?=?new?Message(); ? 70.???????????m.what?=?Activity01.GUI_THREADING_NOTIFIER; ? 71.???????????Activity01.this.myMessageHandler.sendMessage(m); ? 72.?//將message發送到消息隊列 ? 73.????????????????????????????????} ? 74.????????????????????????????} ? 75.????????????????????????????catch?(Exception?e) ? 76.????????????????????????????{ ? 77.????????????????????????????????e.printStackTrace(); ? 78.????????????????????????????} ? 79.????????????????????????} ? 80.????????????????????} ? 81.????????????????}).start(); ? 82.????????????} ? 83.????????}); ? 84.????} ? 85.? 86.//通過匿名類復寫Handler類中的handleMessage方法,用于接收傳遞到消息隊列中的Message,并進行UI操作。 87.??????Handler?myMessageHandler?=?new?Handler() ? 88.??????{ ? 89.????????//?@Override?? 90.??????????public?void?handleMessage(Message?msg) ? 91.??????????{ ? 92.??????????????switch?(msg.what) ? 93.??????????????{ ? 94.??????????????//ProgressBar已經是對大值? 95.??????????????case?Activity01.GUI_STOP_NOTIFIER: ? 96.??????????????????m_ProgressBar.setVisibility(View.GONE); ? 97.??????????????????m_ProgressBar2.setVisibility(View.GONE); ? 98.??????????????????Thread.currentThread().interrupt(); ? 99.??????????????????break; ? 100. ??????????????case?Activity01.GUI_THREADING_NOTIFIER: ? 101. ??????????????????if?(!Thread.currentThread().isInterrupted()) ? 102. ??????????????????{ ? 103. ??????????????????????//?改變ProgressBar的當前值? 104. ??????????????????????m_ProgressBar.setProgress(intCounter); ? 105. ??????????????????????m_ProgressBar2.setProgress(intCounter); ? 106. ?????????????????????? ? 107. ??????????????????????//?設置標題欄中前景的一個進度條進度值? 108. ??????????????????????setProgress(intCounter*100); ? 109. ??????????????????????//?設置標題欄中后面的一個進度條進度值? 110. ??????????????????????setSecondaryProgress(intCounter*100);//? 111. ??????????????????} ? 112. ??????????????????break; ? 113. ??????????????} ? 114. ??????????????super.handleMessage(msg); ? 115. ?????????} ? 116. ??????}; ? 117. } ? |
??? 以上的例子中,子線程只是對進度條的參數進行了變更,并將結果以message形式發送到消息隊列中去,子線程的內部并未進行UI操作,而是在重寫的Handler的handlerMessage方法中操作了UI界面。
??? 2.傳遞Runnable對象。用于通過Handler綁定的消息隊列,安排不同操作的執行順序。
??? Handler對象在進行初始化的時候,會默認的自動綁定消息隊列。利用類post方法,可以將Runnable對象發送到消息隊列中,按照隊列的機制按順序執行不同的Runnable對象中的run方法。
???
| ? 1.? public?class?HandlerActivity?extends?Activity?{ ? 2.? ????/**?Called?when?the?activity?is?first?created.?*/? 3.? ????//聲明兩個按鈕控件? 4.? ????private?Button?startButton?=?null; ? 5.? ????private?Button?endButton?=?null; ? 6.? ????@Override? 7.? ????public?void?onCreate(Bundle?savedInstanceState)?{ ? 8.? ????????super.onCreate(savedInstanceState); ? 9.? ????????setContentView(R.layout.main); ? 10.????????//根據控件的ID得到代表控件的對象,并未這兩個按鈕設置相應的監聽器? 11.????????startButton?=?(Button)findViewById(R.id.startButton); ? 12.????????startButton.setOnClickListener(new?StartButtonListener()); ? 13.????????endButton?=?(Button)findViewById(R.id.endButton); ? 14.????????endButton.setOnClickListener(new?EndButtonListener()); ? 15.???????? ? 16.????} ? 17.????class?StartButtonListener?implements?OnClickListener{ ? 18.? 19.????????@Override? 20.????????public?void?onClick(View?v)?{ ? 21.????????????//調用Handler的post方法,將要執行的線程對象添加到隊列當中? 22.????????????handler.post(updateThread); ? 23.????????} ? 24.???????? ? 25.????} ? 26.???? ? 27.????class?EndButtonListener?implements?OnClickListener{ ? 28.? 29.????????@Override? 30.????????public?void?onClick(View?v)?{ ? 31.????????????handler.removeCallbacks(updateThread); ? 32.????????} ? 33.???????? ? 34.????} ? 35.????//創建一個Handler對象? 36.????Handler?handler??=?new?Handler(); ? 37.????//將要執行的操作寫在線程對象的run方法當中? 38.????Runnable?updateThread?=??new?Runnable(){ ? 39.? 40.????????@Override? 41.????????public?void?run()?{ ? 42.????????????System.out.println("UpdateThread"); ? 43.????????????//在run方法內部,執行postDelayed或者是post方法? 44.????????????handler.postDelayed(updateThread,?3000); ? 45.????????} ? 46.???????? ? 47.????}; ? 48.}? |
??? 程序的運行結果就是每隔3秒鐘,就會在控制臺打印一行UpdateTread。這是因為實現了Runnable接口的updateThread對象進入了空的消息隊列即被立即執行run方法,而在run方法的內部,又在3000ms之后將其再次發送進入消息隊列中。
?? 3. Handler和多線程
??? post方法雖然發送的是一個實現了Runnable接口的類對象,但是它并非創建了一個新線程,而是執行了該對象中的run方法。也就是說,整個run中的操作和主線程處于同一個線程。
??? 這樣對于那些簡單的操作,似乎并不會影響。但是對于耗時較長的操作,當它被加入到消息隊列中之后執行會占用很長的時間,以至于處于同一線程的其他操作無法繼續執行,就會出現“假死”。為了解決這個問題,就需要使得handler綁定到一個新開啟線程的消息隊列上,在這個處于另外線程的上的消息隊列中處理傳過來的Runnable對象和消息。SDK文檔中也提供了相關說明:
| ???? When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the samepost or sendMessage methods as before, but from your new thread. The given Runnable or Message will than be scheduled in the Handler's message queue and processed when appropriate. |
???? 具體操作方法如下:
| ? 1.? public?class?HandlerTest2?extends?Activity?{ ? 2.? ? 3.? ????@Override? 4.? ????protected?void?onCreate(Bundle?savedInstanceState)?{ ? 5.? ????????//?TODO?Auto-generated?method?stub? 6.? ????super.onCreate(savedInstanceState); ? 7.? ????setContentView(R.layout.main); ? 8.? ????//打印了當前線程的ID? 9.? ????System.out.println("Activity-->"?+?Thread.currentThread().getId()); ? 10.????//生成一個HandlerThread對象? 11.????HandlerThread?handlerThread?=?new?HandlerThread("handler_thread"); ? 12.????//在使用HandlerThread的getLooper()方法之前,必須先調用該類的start(),同時開啟一個新線程;? 13.????handlerThread.start(); 14.???//將由HandlerThread獲取的Looper傳遞給Handler對象,即由處于另外線程的Looper代替handler初始化時默認綁定的消息隊列來處理消息。 ? 15.????MyHandler?myHandler?=?new?MyHandler(handlerThread.getLooper()); ? 16.????Message?msg?=?myHandler.obtainMessage(); ? 17.????//將msg發送到目標對象,所謂的目標對象,就是生成該msg對象的handler對象? 18.????Bundle?b?=?new?Bundle(); ? 19.????b.putInt("age",?20); ? 20.????b.putString("name",?"Jhon"); ? 21.????msg.setData(b); ? 22.????msg.sendToTarget(); ?//將msg發送到myHandler 23.????} ? 24.???? ? 25.???//定義類 26.????class?MyHandler?extends?Handler{ ? 27.????public?MyHandler(){ ? 28.???????????? ? 29.????} ? 30.??? 31.????public?MyHandler(Looper?looper){ ? 32.????????super(looper); ? 33.????} ? 34.????@Override? 35.????public?void?handleMessage(Message?msg)?{ ? 36.????????Bundle?b?=?msg.getData(); ? 37.????????int?age?=?b.getInt("age"); ? 38.????????String?name?=?b.getString("name"); ? 39.????????System.out.println("age?is?"?+?age?+?",?name?is"?+?name); ? 40.????????System.out.println("Handler--->"?+?Thread.currentThread().getId()); ? 41.????????System.out.println("handlerMessage"); ? 42.????????} ? 43.????} ? 44.} ? |
??? 這樣,當使用sendMessage方法傳遞消息或者使用post方法傳遞Runnable對象時,就會把它們傳遞到與handler對象綁定的處于另外一個線程的消息隊列中,它們將在另外的消息隊列中被處理。而主線程還會在發送操作完成時候繼續進行,不會影響當前的操作。
??? 這里需要注意,這里用到的多線程并非由Runnable對象開啟的,而是ThreadHandler對象開啟的。Runnable對象只是作為一個封裝了操作的對象被傳遞,并未產生新線程。
?
?
總結
以上是生活随笔為你收集整理的androidHandler讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GideView 动态列模板
- 下一篇: STP、RSTP、MSTP